From 0b553a1551836092fe4dfbea7eda8fb6a3291f9a Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 22 May 2026 17:02:20 +0800 Subject: [PATCH 01/37] Add direct Lean agent skill --- SKILL.md | 55 ++++ agents/openai.yaml | 3 + config/env.example | 3 + config/lean_agent.example.toml | 28 ++ prompts/complete_sorries.md | 3 + prompts/formalize_statement.md | 3 + prompts/prove_theorem.md | 3 + prompts/repair_lean_file.md | 3 + references/direct_lean_workflow.md | 45 ++++ references/failure_taxonomy.md | 17 ++ references/interactive_orchestration.md | 33 +++ references/lean_runtime_configuration.md | 69 +++++ references/numina_reverse_analysis.md | 78 ++++++ references/review_checklist.md | 10 + schemas/config.schema.json | 11 + schemas/result.schema.json | 32 +++ schemas/task.schema.json | 30 +++ scripts/ai4m_lean.py | 206 ++++++++++++++ scripts/check_lean_project.py | 134 +++++++++ scripts/common.py | 285 ++++++++++++++++++++ scripts/configure_lean.py | 185 +++++++++++++ scripts/detect_sorry.py | 49 ++++ scripts/direct_task.py | 100 +++++++ scripts/extract_minimal_failure.py | 74 +++++ scripts/tool_status.py | 79 ++++++ scripts/validate_patch.py | 81 ++++++ scripts/verify_delivery.py | 244 +++++++++++++++++ tests/fixtures/after_bad.lean | 4 + tests/fixtures/after_statement_changed.lean | 4 + tests/fixtures/before.lean | 4 + tests/fixtures/failure.lean | 7 + tests/test_check_lean_project.py | 59 ++++ tests/test_cli.py | 103 +++++++ tests/test_common_config.py | 55 ++++ tests/test_configure_lean.py | 67 +++++ tests/test_detect_sorry.py | 24 ++ tests/test_direct_task.py | 64 +++++ tests/test_validate_patch.py | 29 ++ 38 files changed, 2283 insertions(+) create mode 100644 SKILL.md create mode 100644 agents/openai.yaml create mode 100644 config/env.example create mode 100644 config/lean_agent.example.toml create mode 100644 prompts/complete_sorries.md create mode 100644 prompts/formalize_statement.md create mode 100644 prompts/prove_theorem.md create mode 100644 prompts/repair_lean_file.md create mode 100644 references/direct_lean_workflow.md create mode 100644 references/failure_taxonomy.md create mode 100644 references/interactive_orchestration.md create mode 100644 references/lean_runtime_configuration.md create mode 100644 references/numina_reverse_analysis.md create mode 100644 references/review_checklist.md create mode 100644 schemas/config.schema.json create mode 100644 schemas/result.schema.json create mode 100644 schemas/task.schema.json create mode 100644 scripts/ai4m_lean.py create mode 100644 scripts/check_lean_project.py create mode 100644 scripts/common.py create mode 100644 scripts/configure_lean.py create mode 100644 scripts/detect_sorry.py create mode 100644 scripts/direct_task.py create mode 100644 scripts/extract_minimal_failure.py create mode 100644 scripts/tool_status.py create mode 100644 scripts/validate_patch.py create mode 100644 scripts/verify_delivery.py create mode 100644 tests/fixtures/after_bad.lean create mode 100644 tests/fixtures/after_statement_changed.lean create mode 100644 tests/fixtures/before.lean create mode 100644 tests/fixtures/failure.lean create mode 100644 tests/test_check_lean_project.py create mode 100644 tests/test_cli.py create mode 100644 tests/test_common_config.py create mode 100644 tests/test_configure_lean.py create mode 100644 tests/test_detect_sorry.py create mode 100644 tests/test_direct_task.py create mode 100644 tests/test_validate_patch.py diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..148cf68 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,55 @@ +--- +name: ai4math-lean-agents +description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, theorem formalization, sorry completion, patch review, and minimal failure handoff. +--- + +# AI4Math Lean Agents + +Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, or review of a Lean patch. The active coding agent is the Lean agent: it asks clarifying questions, reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, and iterates with the user. + +The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake commands, and repository context. Use helper commands only when their deterministic output is useful. + +Numina is not deployed or called by this skill. Its public workflow is used only as design provenance in `references/numina_reverse_analysis.md`. + +## Agent Playbook + +1. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. +2. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available. +3. For standalone files, use or create `.ai4math/lean-workspace` only when a project context is needed. +4. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. +5. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. +6. Preserve theorem statements unless the user explicitly approves a change. +7. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. +8. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. + +## Helper Toolbox + +Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk: + +- `env` / `doctor`: inspect Lean workspace and local tool availability. +- `configure --create-workspace`: create or reuse the managed workspace. +- `check`: run a structured Lean/Lake validation. +- `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. +- `minimize-failure`: extract a compact failing Lean fragment. +- `prove` / `formalize` / `repair` / `complete-sorries` / `batch`: optional dry-run task envelopes for bookkeeping; do not treat them as required proof engines. +- `verify-delivery`: validate this skill package. + +All helper commands emit machine-readable JSON on stdout. Human-readable diagnostics go to stderr or log files. + +## Safety Rules + +- Do not require Numina, Claude Code CLI, external model APIs, or API keys for this skill. +- Do not commit local machine-specific paths. +- Do not call external APIs during `env`, `configure`, `check`, `review`, `detect-sorry`, tests, or dry-runs. +- Do not accept final Lean patches containing `sorry`, `admit`, or newly introduced `axiom`. +- Do not silently weaken theorem statements or change existing project versions. +- Do not let helper command availability override a better direct coding-agent path. + +## References + +- Read `references/direct_lean_workflow.md` for the full guidance-first proof/repair/formalization loop. +- Read `references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. +- Read `references/interactive_orchestration.md` when guiding user intake and task decomposition. +- Read `references/review_checklist.md` before accepting a Lean patch. +- Read `references/failure_taxonomy.md` when reporting a blocked proof. +- Read `references/numina_reverse_analysis.md` only when explaining which Numina mechanisms were distilled into this direct AI4Math skill. diff --git a/agents/openai.yaml b/agents/openai.yaml new file mode 100644 index 0000000..038ad9a --- /dev/null +++ b/agents/openai.yaml @@ -0,0 +1,3 @@ +display_name: AI4Math Lean Agents +short_description: Interactive Lean 4 verification with reusable mathlib workspaces. +default_prompt: Use the Lean agent playbook to directly formalize, prove, repair, review, or minimize this Lean task; use helper CLI checks only when useful. diff --git a/config/env.example b/config/env.example new file mode 100644 index 0000000..e41e5ae --- /dev/null +++ b/config/env.example @@ -0,0 +1,3 @@ +# Copy values into an ignored local file or export them manually. +export AI4MATH_LEAN_WORKSPACE=".ai4math/lean-workspace" +export AI4MATH_LEAN_TOOLCHAIN="leanprover/lean4:v4.28.0" diff --git a/config/lean_agent.example.toml b/config/lean_agent.example.toml new file mode 100644 index 0000000..0d6ef5a --- /dev/null +++ b/config/lean_agent.example.toml @@ -0,0 +1,28 @@ +[lean] +default_cwd = "." +validate_command = "lake build" +single_file_check_template = "lake env lean {file}" +workspace_mode = "reuse-managed" +managed_workspace_path = ".ai4math/lean-workspace" +managed_workspace_root = ".ai4math/lean-workspaces" +managed_workspace_template = "math" +reuse_managed_workspace = true +workspace_key = "lean-toolchain" +align_workspace_versions = true +preferred_toolchain = "auto" +preferred_mathlib_rev = "auto" +allow_user_project_version_changes = false + +[agent] +mode = "direct-coding-agent" +backend = "none" +max_local_iterations = 5 +require_user_statement_confirmation = true + +[policy] +no_sorry = true +no_admit = true +no_axiom = true +do_not_change_statement = true +allow_new_lemmas = true +default_max_rounds = 5 diff --git a/prompts/complete_sorries.md b/prompts/complete_sorries.md new file mode 100644 index 0000000..8ecad1f --- /dev/null +++ b/prompts/complete_sorries.md @@ -0,0 +1,3 @@ +# Complete Sorries Prompt + +Replace `sorry` placeholders with complete Lean proofs. Preserve declarations and report any remaining goals that cannot be solved within the round limit. diff --git a/prompts/formalize_statement.md b/prompts/formalize_statement.md new file mode 100644 index 0000000..86247d5 --- /dev/null +++ b/prompts/formalize_statement.md @@ -0,0 +1,3 @@ +# Formalize Statement Prompt + +Translate the source mathematical statement into a Lean declaration in the target file. First preserve meaning and ask for confirmation when the statement is ambiguous. Do not begin long proof search until the declaration is confirmed. diff --git a/prompts/prove_theorem.md b/prompts/prove_theorem.md new file mode 100644 index 0000000..fb8be0d --- /dev/null +++ b/prompts/prove_theorem.md @@ -0,0 +1,3 @@ +# Prove Theorem Prompt + +Prove the target Lean declaration without changing its statement. You may add helper lemmas and imports when appropriate. Return JSON with changed files, validation status, remaining goals, and next action. diff --git a/prompts/repair_lean_file.md b/prompts/repair_lean_file.md new file mode 100644 index 0000000..a2c32e1 --- /dev/null +++ b/prompts/repair_lean_file.md @@ -0,0 +1,3 @@ +# Repair Lean File Prompt + +Repair Lean errors in the target file while preserving theorem statements. Prefer small local edits, import fixes, and helper lemmas. Do not hide errors with `sorry`, `admit`, or `axiom`. diff --git a/references/direct_lean_workflow.md b/references/direct_lean_workflow.md new file mode 100644 index 0000000..aff3445 --- /dev/null +++ b/references/direct_lean_workflow.md @@ -0,0 +1,45 @@ +# Direct Lean Coding-Agent Workflow + +This skill distills the useful workflow pattern from Numina without deploying or calling Numina. The active coding agent is the Lean proof worker; helper CLI commands are optional guardrails. + +## Guidance-First Loop + +1. Read the user's request and classify the mathematical task. +2. Inspect the target files, imports, nearby lemmas, and current Lean errors. +3. Choose the validation context: existing Lake project first, managed workspace only for standalone files. +4. For formalization, draft the Lean declaration and ask for confirmation before long proof work. +5. Make one small Lean edit at a time. +6. Run direct Lean/Lake validation after meaningful edits, usually `lake env lean `, `lake build`, or the helper `check` command. +7. Diagnose the first concrete Lean error or unsolved goal before changing strategy. +8. Add helper lemmas only when they reduce proof complexity and keep theorem statements unchanged. +9. Review the final patch with direct inspection and, when useful, `review` or `detect-sorry`. +10. If blocked, use direct reduction and/or `minimize-failure` to return the smallest failing Lean fragment plus exact errors/goals. + +## When to Use Helpers + +Use helpers for mechanical checks: + +- environment and workspace readiness: `env`, `doctor`, `configure`; +- validation: `check`; +- safety guards: `review`, `detect-sorry`; +- failure handoff: `minimize-failure`; +- package QA: `verify-delivery`. + +Do not route creative proof search through helper commands. `prove`, `formalize`, `repair`, `complete-sorries`, and `batch` only produce optional task envelopes for bookkeeping; they are not proof engines and should not constrain how the coding agent edits Lean. + +## Workspace Choice + +Prefer a user's existing Lake project when the target file is inside one. For standalone `.lean` files, use the reusable `.ai4math/lean-workspace` so Lean, Lake, and mathlib artifacts are shared across tasks. + +When a user project has its own `lean-toolchain` and mathlib revision, keep those versions unless the user explicitly approves a change. When creating a managed workspace, use the configured preferred toolchain or `auto`. + +## Good Stopping Points + +Stop with success when the relevant Lean file or project validates and no unsafe placeholders remain. + +Stop with a minimal failure when: + +- the remaining proof step requires a human mathematical decision; +- the theorem statement appears ambiguous or unconfirmed; +- progress would require weakening a statement without approval; +- repeated local attempts are cycling over the same Lean error. diff --git a/references/failure_taxonomy.md b/references/failure_taxonomy.md new file mode 100644 index 0000000..46168f2 --- /dev/null +++ b/references/failure_taxonomy.md @@ -0,0 +1,17 @@ +# Failure Taxonomy + +Use these categories in result JSON and summaries: + +- `missing_lean_project`: target is not inside a Lake project and no managed workspace is available. +- `lean_workspace_setup_failed`: creating or building the reusable managed workspace failed. +- `lean_build_failed`: `lake build` failed for the target project or managed workspace. +- `lean_file_failed`: single-file Lean validation failed. +- `target_missing`: requested Lean file or folder does not exist. +- `statement_ambiguous`: natural-language theorem needs user confirmation. +- `statement_unconfirmed`: long proof work should wait until the user confirms the Lean declaration. +- `statement_changed`: patch changed the theorem statement without approval. +- `unsafe_patch`: patch introduced `sorry`, `admit`, or `axiom`. +- `proof_budget_exhausted`: max local iterations reached with remaining goals. +- `human_math_decision_needed`: remaining step needs a mathematical lemma or strategy decision. + +This direct skill should not report Numina, model, API-key, Claude-login, or external-backend failures because those are not runtime dependencies. diff --git a/references/interactive_orchestration.md b/references/interactive_orchestration.md new file mode 100644 index 0000000..4cb0793 --- /dev/null +++ b/references/interactive_orchestration.md @@ -0,0 +1,33 @@ +# Interactive Orchestration + +The coordinating coding agent owns both user interaction and proof iteration. It does not delegate proof search to Numina, helper CLI commands, or any external backend. + +This reference covers the guidance layer: intake, task classification, decomposition, direct Lean editing, result review, bounded iteration, and minimal failure handoff. + +## Intake Questions + +Ask only when not inferable: + +- Is this repair, theorem formalization, proof completion, sorry completion, patch review, or batch work? +- What target file/folder and declaration should be used? +- Is changing the theorem statement allowed? +- Should standalone work use the reusable managed workspace? +- For natural-language or LaTeX input, what statement should be considered authoritative? + +## Decomposition + +Break large requests into small Lean targets that can be checked with direct Lean/Lake commands or the optional helper `check` command. + +For natural-language or LaTeX statements, draft the Lean declaration first and ask for confirmation before long proof work. Once the declaration is confirmed, treat statement preservation as a hard guardrail. + +## Iteration Policy + +Stop when: + +- validation succeeds without `sorry`, `admit`, or new `axiom`; +- max local iterations are reached; +- Lean workspace setup is missing or broken; +- the remaining error requires a human mathematical decision; +- the only path forward would weaken the theorem statement without approval. + +When stopping before success, reduce the problem to the smallest useful failing fragment. Use `minimize-failure` when it helps, then report exact Lean errors/goals and the next human decision needed. diff --git a/references/lean_runtime_configuration.md b/references/lean_runtime_configuration.md new file mode 100644 index 0000000..28897d5 --- /dev/null +++ b/references/lean_runtime_configuration.md @@ -0,0 +1,69 @@ +# Lean Runtime Configuration + +This skill uses a direct coding-agent workflow. It does not deploy Numina, run a Numina Python environment, or require Claude Code/API credentials as a backend. + +## Local Layout + +```text +.ai4math/ +├── lean-workspace/ +├── lean-workspaces/ +├── lean_agent.local.toml +├── logs/ +└── failures/ +``` + +The skill should create `.ai4math/.gitignore` before writing local config. + +## Tool Checks + +Use: + +```bash +python scripts/ai4m_lean.py doctor --cwd . +python scripts/ai4m_lean.py env --cwd . +``` + +Required local tools for the direct workflow are `git`, `python3`, `elan`, `lean`, and `lake`. `uv`, `claude`, Numina, and model API keys are not required by this skill. + +## Reusable Lean Workspace + +For standalone tasks, prefer `.ai4math/lean-workspace`. Create it once with: + +```bash +python scripts/ai4m_lean.py configure --cwd . --create-workspace --toolchain leanprover/lean4:v4.28.0 +``` + +Equivalent Lake commands: + +```bash +lake new lean_workspace math +lake update +lake exe cache get +lake build +``` + +If a user project already has `lean-toolchain` and `lakefile.{lean,toml}`, use that project and do not change versions without approval. If a standalone task needs a different Lean/mathlib revision than the managed workspace, use a versioned workspace under `.ai4math/lean-workspaces/`. + +## Local Config + +Machine-specific settings live in `.ai4math/lean_agent.local.toml` and should not be committed. Example: + +```toml +[lean] +workspace_mode = "reuse-managed" +managed_workspace_path = ".ai4math/lean-workspace" +align_workspace_versions = true +preferred_toolchain = "auto" + +[agent] +mode = "direct-coding-agent" +backend = "none" +``` + +Environment overrides: + +```bash +export AI4MATH_LEAN_WORKSPACE=".ai4math/lean-workspace" +export AI4MATH_LEAN_TOOLCHAIN="leanprover/lean4:v4.28.0" +``` diff --git a/references/numina_reverse_analysis.md b/references/numina_reverse_analysis.md new file mode 100644 index 0000000..3d06f2f --- /dev/null +++ b/references/numina_reverse_analysis.md @@ -0,0 +1,78 @@ +# Numina Reverse Analysis for AI4Math + +This reference records what was distilled from the public Numina Lean Agent workflow. It is design provenance only. The AI4Math Lean Agents skill does not install, deploy, configure, import, or call Numina at runtime. + +## Source Scope + +- Public repository: https://github.com/project-numina/numina-lean-agent +- Result repository: https://github.com/project-numina/Numina-Putnam2025 +- Paper reference: https://arxiv.org/abs/2601.14027 + +The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to extract reusable workflow patterns for direct coding-agent Lean work. + +## Distilled Patterns + +1. Use a coding agent as the Lean worker, not merely as a chat layer. +2. Keep Lean/Lake validation as the correctness oracle. +3. Treat theorem statement preservation as a first-class safety check. +4. Work in bounded rounds with a clear stopping condition. +5. Preserve structured run state: task type, target, changed files, validation result, remaining errors/goals, and next action. +6. When blocked, reduce the problem to the smallest useful failing Lean fragment. +7. Prefer reusable Lean workspaces so setup cost is not paid on every standalone problem. + +## What Was Removed + +The direct AI4Math skill intentionally removes these runtime dependencies: + +- upstream Numina repository checkout; +- Numina Python environment; +- external prover backend command construction; +- model endpoint configuration; +- API-key or login setup; +- backend round streaming or benchmark execution. + +Those concerns made sense for the original system, but they are not part of this skill's delivery target. + +## Adapted Direct Workflow + +```mermaid +flowchart TD + A["User asks for Lean work"] --> B["Coding agent classifies task"] + B --> C["Inspect Lean project or managed workspace"] + C --> D["Coding agent edits Lean directly"] + D --> E["Run Lean/Lake check"] + E --> F{"Verified without unsafe placeholders?"} + F -->|yes| G["Review patch and return result"] + F -->|no| H{"Useful local iteration remains?"} + H -->|yes| D + H -->|no| I["Extract minimal failure and report exact errors/goals"] +``` + +## AI4Math Skill Mapping + +| Numina-inspired idea | Direct AI4Math implementation | +| --- | --- | +| Environment gate before proof attempts | `env`, `doctor`, `configure`, `check` | +| Structured task envelope | `direct_task.py` and JSON schemas | +| Bounded proof rounds | `max_local_iterations` / `max_rounds` | +| Statement drift guard | `validate_patch.py` | +| Placeholder guard | `detect_sorry.py` and `review` | +| Minimal blocked artifact | `extract_minimal_failure.py` | +| Reusable project context | `.ai4math/lean-workspace` | + +## Failure Lessons + +- Standalone Lean files need a project context; the skill supplies a managed workspace. +- Long proof attempts should wait until a natural-language statement has been translated and confirmed. +- A patch that proves an easier theorem is a failure unless the user approved the statement change. +- Partial progress is valuable only when the remaining Lean errors/goals are preserved precisely. + +## Practical Rule + +If a future agent reads this file during normal Lean work, the action item is not "run Numina." The action item is: + +1. use the direct skill CLI to verify local Lean readiness; +2. edit Lean directly; +3. run Lean/Lake checks frequently; +4. review safety constraints; +5. return a verified patch or minimal failure. diff --git a/references/review_checklist.md b/references/review_checklist.md new file mode 100644 index 0000000..7c6ffe7 --- /dev/null +++ b/references/review_checklist.md @@ -0,0 +1,10 @@ +# Review Checklist + +Before accepting a Lean patch: + +1. Run `detect-sorry` or `review`. +2. Confirm no `sorry`, `admit`, or newly introduced `axiom`. +3. Confirm theorem/lemma declarations were not weakened unless approved. +4. Run `lake env lean ` or `check` when available. +5. If validation fails, run `minimize-failure`. +6. Report remaining errors and exact next action. diff --git a/schemas/config.schema.json b/schemas/config.schema.json new file mode 100644 index 0000000..a93587d --- /dev/null +++ b/schemas/config.schema.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "AI4Math Lean Agent Config", + "type": "object", + "properties": { + "lean": {"type": "object", "additionalProperties": true}, + "agent": {"type": "object", "additionalProperties": true}, + "policy": {"type": "object", "additionalProperties": true} + }, + "additionalProperties": false +} diff --git a/schemas/result.schema.json b/schemas/result.schema.json new file mode 100644 index 0000000..7302666 --- /dev/null +++ b/schemas/result.schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "AI4Math Lean Agent Result", + "type": "object", + "properties": { + "ok": {"type": "boolean"}, + "status": {"type": "string"}, + "agent_mode": {"type": "string"}, + "backend": {"type": "string"}, + "task_type": {"type": "string"}, + "cwd": {"type": "string"}, + "target": {"type": "string"}, + "project_root": {"type": ["string", "null"]}, + "target_project_root": {"type": ["string", "null"]}, + "workspace_project_root": {"type": ["string", "null"]}, + "workspace_path": {"type": ["string", "null"]}, + "workspace_mode": {"type": "string"}, + "toolchain": {"type": ["string", "null"]}, + "mathlib_revision": {"type": ["string", "null"]}, + "configuration_status": {"type": "string"}, + "missing_config": {"type": "array", "items": {"type": "string"}}, + "required_inputs": {"type": "array", "items": {"type": "string"}}, + "direct_workflow": {"type": "array", "items": {"type": "string"}}, + "changed_files": {"type": "array", "items": {"type": "string"}}, + "errors": {"type": "array", "items": {"type": "object", "additionalProperties": true}}, + "warnings": {"type": "array", "items": {"type": "object", "additionalProperties": true}}, + "minimal_failure": {"type": "object", "additionalProperties": true}, + "recommended_next_action": {"type": "string"} + }, + "required": ["ok", "status"], + "additionalProperties": true +} diff --git a/schemas/task.schema.json b/schemas/task.schema.json new file mode 100644 index 0000000..c54bb6f --- /dev/null +++ b/schemas/task.schema.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "AI4Math Lean Agent Task", + "type": "object", + "properties": { + "task_id": {"type": "string"}, + "task_type": { + "type": "string", + "enum": ["check", "configure", "prove_theorem", "formalize_statement", "repair_file", "complete_sorries", "batch", "review", "minimize_failure"] + }, + "agent_mode": {"type": "string", "enum": ["direct-coding-agent"], "default": "direct-coding-agent"}, + "backend": {"type": "string", "enum": ["none"], "default": "none"}, + "cwd": {"type": "string"}, + "file": {"type": "string"}, + "folder": {"type": "string"}, + "target": {"type": "string"}, + "source_statement": {"type": "string"}, + "source_statement_file": {"type": "string"}, + "source_format": {"type": "string", "enum": ["natural_language", "latex", "lean", "mixed"]}, + "statement_confirmed": {"type": "boolean", "default": false}, + "interaction_mode": {"type": "string", "enum": ["interactive", "noninteractive"], "default": "interactive"}, + "configuration": {"type": "object", "additionalProperties": true}, + "subtasks": {"type": "array", "items": {"type": "object", "additionalProperties": true}}, + "max_rounds": {"type": "integer", "minimum": 1, "default": 5}, + "dry_run": {"type": "boolean", "default": false}, + "constraints": {"type": "object", "additionalProperties": true} + }, + "required": ["task_type"], + "additionalProperties": false +} diff --git a/scripts/ai4m_lean.py b/scripts/ai4m_lean.py new file mode 100644 index 0000000..e9a55d5 --- /dev/null +++ b/scripts/ai4m_lean.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +from check_lean_project import check_file, check_project +from common import emit_json +from configure_lean import configure, inspect_environment +from detect_sorry import scan_file +from direct_task import run_direct_task +from extract_minimal_failure import extract +from tool_status import doctor +from validate_patch import review_files +from verify_delivery import verify as verify_delivery + + +EXIT_OK = 0 +EXIT_MISSING_CONFIG = 4 +EXIT_LEAN_FAILED = 6 +EXIT_PATCH_VIOLATION = 7 +EXIT_INTERACTIVE_REQUIRED = 10 + + +def _exit_code(result: dict[str, Any], default_fail: int = 1) -> int: + if result.get("ok"): + return EXIT_OK + status = result.get("status") + if status in {"missing_config", "direct_task_missing_config"}: + return EXIT_MISSING_CONFIG + if status in {"missing_lean_project", "lean_build_failed", "lean_file_failed", "lean_workspace_setup_failed"}: + return EXIT_LEAN_FAILED + if status == "patch_safety_violation": + return EXIT_PATCH_VIOLATION + if status == "interactive_required": + return EXIT_INTERACTIVE_REQUIRED + return default_fail + + +def _finish(result: dict[str, Any], json_output: str | None = None, fail_code: int = 1) -> None: + emit_json(result, json_output=json_output) + raise SystemExit(_exit_code(result, default_fail=fail_code)) + + +def add_common(parser: argparse.ArgumentParser) -> None: + parser.add_argument("--cwd", default=".", help="Lean project or workspace directory") + parser.add_argument("--config", default=None, help="Optional TOML config path") + parser.add_argument("--json-output", default=None, help="Write JSON result to this path") + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="AI4Math direct Lean coding-agent skill CLI") + sub = parser.add_subparsers(dest="command", required=True) + + env = sub.add_parser("env", help="Inspect direct Lean agent environment") + add_common(env) + env.add_argument("--target", default=None) + + doctor_parser = sub.add_parser("doctor", help="Report local tool availability") + add_common(doctor_parser) + + check = sub.add_parser("check", help="Check Lean project or file") + add_common(check) + check.add_argument("--file", default=None) + check.add_argument("--skip-build", action="store_true") + check.add_argument("--timeout", type=int, default=300) + + configure_parser = sub.add_parser("configure", help="Inspect or create local Lean workspace configuration") + add_common(configure_parser) + configure_parser.add_argument("--target", default=None) + configure_parser.add_argument("--create-workspace", action="store_true") + configure_parser.add_argument("--toolchain", default=None, help="Optional Lean toolchain for managed workspace") + configure_parser.add_argument("--save-local", action="store_true") + configure_parser.add_argument("--dry-run", action="store_true") + + for name in ("prove", "formalize", "repair", "complete-sorries"): + proof = sub.add_parser(name, help=f"Prepare a direct coding-agent {name} task") + add_common(proof) + proof.add_argument("--file", required=True) + proof.add_argument("--target", default=None) + proof.add_argument("--max-rounds", type=int, default=5) + proof.add_argument("--prompt-file", default=None) + proof.add_argument("--result-dir", default=None) + proof.add_argument("--dry-run", action="store_true") + if name == "formalize": + proof.add_argument("--statement-file", default=None) + + batch = sub.add_parser("batch", help="Prepare a direct coding-agent folder task") + add_common(batch) + batch.add_argument("--folder", required=True) + batch.add_argument("--max-rounds", type=int, default=5) + batch.add_argument("--prompt-file", default=None) + batch.add_argument("--result-dir", default=None) + batch.add_argument("--dry-run", action="store_true") + + review = sub.add_parser("review", help="Review before/after Lean patch") + review.add_argument("--before", required=True) + review.add_argument("--after", required=True) + review.add_argument("--allow-statement-changes", action="store_true") + review.add_argument("--json-output", default=None) + + detect = sub.add_parser("detect-sorry", help="Detect sorry/admit/axiom") + detect.add_argument("--file", required=True) + detect.add_argument("--json-output", default=None) + + minimize = sub.add_parser("minimize-failure", help="Extract a small failing Lean fragment") + add_common(minimize) + minimize.add_argument("--file", required=True) + minimize.add_argument("--target", default=None) + minimize.add_argument("--run-lean", action="store_true") + minimize.add_argument("--timeout", type=int, default=120) + + delivery = sub.add_parser("verify-delivery", help="Run delivery readiness checks for this skill") + add_common(delivery) + delivery.add_argument("--require-environment", action="store_true") + delivery.add_argument("--include-workspace-build", action="store_true") + delivery.add_argument("--run-tests", action="store_true") + + return parser + + +def main(argv: list[str] | None = None) -> None: + args = build_parser().parse_args(argv) + + if args.command == "env": + result = inspect_environment(args.cwd, config_path=args.config, target=args.target) + _finish(result, args.json_output, fail_code=EXIT_MISSING_CONFIG) + + if args.command == "doctor": + result = doctor(args.cwd) + _finish(result, args.json_output) + + if args.command == "check": + if args.file: + result = check_project(args.cwd, skip_build=True, file=args.file, timeout=args.timeout) if args.skip_build else check_file(args.file, timeout=args.timeout) + else: + result = check_project(args.cwd, skip_build=args.skip_build, timeout=args.timeout) + _finish(result, args.json_output, fail_code=EXIT_LEAN_FAILED) + + if args.command == "configure": + result = configure( + args.cwd, + config_path=args.config, + target=args.target, + create_workspace=args.create_workspace, + toolchain=args.toolchain, + save_local=args.save_local, + dry_run=args.dry_run, + ) + _finish(result, args.json_output, fail_code=EXIT_INTERACTIVE_REQUIRED) + + if args.command in {"prove", "formalize", "repair", "complete-sorries"}: + result = run_direct_task( + args.command, + cwd=args.cwd, + target=args.file, + max_rounds=args.max_rounds, + config_path=args.config, + prompt_file=args.prompt_file, + result_dir=args.result_dir, + dry_run=args.dry_run, + ) + if args.command == "formalize" and args.statement_file: + result["statement_file"] = str(Path(args.statement_file).expanduser().resolve()) + if args.target: + result["target_declaration"] = args.target + _finish(result, args.json_output, fail_code=EXIT_MISSING_CONFIG) + + if args.command == "batch": + result = run_direct_task( + "batch", + cwd=args.cwd, + target=args.folder, + max_rounds=args.max_rounds, + config_path=args.config, + prompt_file=args.prompt_file, + result_dir=args.result_dir, + dry_run=args.dry_run, + ) + _finish(result, args.json_output, fail_code=EXIT_MISSING_CONFIG) + + if args.command == "review": + result = review_files(args.before, args.after, allow_statement_changes=args.allow_statement_changes) + _finish(result, args.json_output, fail_code=EXIT_PATCH_VIOLATION) + + if args.command == "detect-sorry": + result = scan_file(args.file) + _finish(result, args.json_output, fail_code=EXIT_PATCH_VIOLATION) + + if args.command == "minimize-failure": + result = extract(args.file, target=args.target, run_lean=args.run_lean, timeout=args.timeout) + _finish(result, args.json_output, fail_code=EXIT_LEAN_FAILED) + + if args.command == "verify-delivery": + result = verify_delivery( + cwd=args.cwd, + require_environment=args.require_environment, + include_workspace_build=args.include_workspace_build, + run_tests=args.run_tests, + ) + _finish(result, args.json_output) + + +if __name__ == "__main__": + main() diff --git a/scripts/check_lean_project.py b/scripts/check_lean_project.py new file mode 100644 index 0000000..f4a629f --- /dev/null +++ b/scripts/check_lean_project.py @@ -0,0 +1,134 @@ +from __future__ import annotations + +import json +import re +from pathlib import Path +from typing import Any + +from common import run_command +from tool_status import find_tool + + +def has_lakefile(path: Path) -> bool: + return (path / "lakefile.toml").exists() or (path / "lakefile.lean").exists() + + +def find_project_root(path: str | Path) -> Path | None: + target = Path(path).expanduser().resolve() + current = target.parent if target.is_file() else target + while True: + if (current / "lean-toolchain").exists() and has_lakefile(current): + return current + if current.parent == current: + return None + current = current.parent + + +def read_toolchain(root: Path | None) -> str | None: + if not root: + return None + toolchain = root / "lean-toolchain" + if not toolchain.exists(): + return None + return toolchain.read_text(encoding="utf-8", errors="replace").strip() or None + + +def _search_manifest(value: Any) -> str | None: + if isinstance(value, dict): + name = value.get("name") + if name == "mathlib": + for key in ("rev", "revision", "inputRev", "gitRev"): + found = value.get(key) + if isinstance(found, str) and found: + return found + for item in value.values(): + found = _search_manifest(item) + if found: + return found + elif isinstance(value, list): + for item in value: + found = _search_manifest(item) + if found: + return found + return None + + +def read_mathlib_revision(root: Path | None) -> str | None: + if not root: + return None + manifest = root / "lake-manifest.json" + if manifest.exists(): + try: + return _search_manifest(json.loads(manifest.read_text(encoding="utf-8"))) + except json.JSONDecodeError: + pass + + for lakefile in (root / "lakefile.toml", root / "lakefile.lean"): + if not lakefile.exists(): + continue + text = lakefile.read_text(encoding="utf-8", errors="replace") + require_match = re.search(r'name\s*=\s*"mathlib".{0,400}?rev\s*=\s*"([^"]+)"', text, re.S) + if require_match: + return require_match.group(1) + lean_match = re.search(r'require\s+mathlib\b.*?@\s*"?([A-Za-z0-9_.:/-]+)"?', text) + if lean_match: + return lean_match.group(1) + return None + + +def check_project(cwd: str | Path = ".", skip_build: bool = False, file: str | Path | None = None, timeout: int = 300) -> dict[str, Any]: + target = Path(file).expanduser().resolve() if file else Path(cwd).expanduser().resolve() + root = find_project_root(target) + result: dict[str, Any] = { + "ok": root is not None, + "status": "ok" if root else "missing_lean_project", + "cwd": str(Path(cwd).expanduser().resolve()), + "target": str(target), + "project_root": str(root) if root else None, + "toolchain": read_toolchain(root), + "mathlib_revision": read_mathlib_revision(root), + "has_lakefile": bool(root and has_lakefile(root)), + "build": None, + "errors": [], + } + if root is None: + result["errors"].append({"severity": "error", "data": "No ancestor contains both lean-toolchain and lakefile.toml/lakefile.lean"}) + return result + if skip_build: + result["status"] = "ok_skip_build" + return result + lake = find_tool("lake") or "lake" + build = run_command([lake, "build"], cwd=root, timeout=timeout) + result["build"] = build + result["ok"] = bool(build["ok"]) + result["status"] = "ok" if build["ok"] else "lean_build_failed" + if not build["ok"]: + result["errors"].append({"severity": "error", "data": build.get("stderr") or build.get("stdout") or "lake build failed"}) + return result + + +def check_file(file: str | Path, timeout: int = 300) -> dict[str, Any]: + file_path = Path(file).expanduser().resolve() + root = find_project_root(file_path) + if root is None: + return { + "ok": False, + "status": "missing_lean_project", + "file": str(file_path), + "project_root": None, + "toolchain": None, + "mathlib_revision": None, + "errors": [{"severity": "error", "data": "File is not inside a Lake project"}], + } + lake = find_tool("lake") or "lake" + run = run_command([lake, "env", "lean", str(file_path)], cwd=root, timeout=timeout) + return { + "ok": bool(run["ok"]), + "status": "ok" if run["ok"] else "lean_file_failed", + "file": str(file_path), + "project_root": str(root), + "toolchain": read_toolchain(root), + "mathlib_revision": read_mathlib_revision(root), + "lean": run, + "errors": [] if run["ok"] else [{"severity": "error", "data": run.get("stderr") or run.get("stdout") or "lean check failed"}], + } diff --git a/scripts/common.py b/scripts/common.py new file mode 100644 index 0000000..71eb948 --- /dev/null +++ b/scripts/common.py @@ -0,0 +1,285 @@ +from __future__ import annotations + +import json +import os +import re +import shlex +import subprocess +import sys +from pathlib import Path +from typing import Any + +try: + import tomllib +except ModuleNotFoundError: # pragma: no cover + try: + import tomli as tomllib # type: ignore[no-redef] + except ModuleNotFoundError: + tomllib = None # type: ignore[assignment] + + +SKILL_ROOT = Path(__file__).resolve().parents[1] +DEFAULT_CONFIG = SKILL_ROOT / "config" / "lean_agent.example.toml" +ENV_KEY_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$") + + +def deep_merge(base: dict[str, Any], overlay: dict[str, Any]) -> dict[str, Any]: + result = dict(base) + for key, value in overlay.items(): + if isinstance(value, dict) and isinstance(result.get(key), dict): + result[key] = deep_merge(result[key], value) + else: + result[key] = value + return result + + +def _parse_simple_value(raw: str) -> Any: + value = raw.strip().rstrip(",") + if value in {"true", "false"}: + return value == "true" + if value.startswith('"') and value.endswith('"'): + try: + return json.loads(value) + except json.JSONDecodeError: + return value[1:-1] + try: + return int(value) + except ValueError: + return value + + +def _load_simple_toml(path: Path) -> dict[str, Any]: + data: dict[str, Any] = {} + section: dict[str, Any] = data + for raw_line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + if line.startswith("[") and line.endswith("]"): + section_name = line[1:-1].strip() + section = data.setdefault(section_name, {}) + continue + if "=" not in line: + continue + key, value = line.split("=", 1) + section[key.strip()] = _parse_simple_value(value) + return data + + +def load_toml(path: Path) -> dict[str, Any]: + if not path.exists(): + return {} + if tomllib is None: + return _load_simple_toml(path) + with path.open("rb") as handle: + data = tomllib.load(handle) + return data if isinstance(data, dict) else {} + + +def expand_path(value: str | None, cwd: Path) -> Path | None: + if not value: + return None + expanded = os.path.expandvars(os.path.expanduser(value)) + path = Path(expanded) + if not path.is_absolute(): + path = cwd / path + return Path(os.path.abspath(path)) + + +def read_config(cwd: str | Path = ".", config_path: str | Path | None = None) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + config = load_toml(DEFAULT_CONFIG) + if config_path: + config = deep_merge(config, load_toml(Path(config_path).expanduser())) + local_config = cwd_path / ".ai4math" / "lean_agent.local.toml" + config = deep_merge(config, load_toml(local_config)) + + env_lean = { + key: value + for key, value in { + "managed_workspace_path": os.environ.get("AI4MATH_LEAN_WORKSPACE"), + "preferred_toolchain": os.environ.get("AI4MATH_LEAN_TOOLCHAIN"), + }.items() + if value + } + if env_lean: + config = deep_merge(config, {"lean": env_lean}) + return config + + +def ensure_ai4math_gitignore(cwd: str | Path) -> Path: + ai4math = Path(cwd).resolve() / ".ai4math" + ai4math.mkdir(parents=True, exist_ok=True) + gitignore = ai4math / ".gitignore" + entries = [ + "lean_agent.local.toml", + ".env.local", + "lean-workspace/", + "lean-workspaces/", + "logs/", + "failures/", + ] + current = gitignore.read_text(encoding="utf-8").splitlines() if gitignore.exists() else [] + merged = list(current) + for entry in entries: + if entry not in merged: + merged.append(entry) + gitignore.write_text("\n".join(merged).rstrip() + "\n", encoding="utf-8") + return gitignore + + +def write_local_toml(cwd: str | Path, values: dict[str, dict[str, Any]]) -> Path: + ensure_ai4math_gitignore(cwd) + path = Path(cwd).resolve() / ".ai4math" / "lean_agent.local.toml" + lines: list[str] = [] + for section, items in values.items(): + lines.append(f"[{section}]") + for key, value in items.items(): + if isinstance(value, bool): + rendered = "true" if value else "false" + elif isinstance(value, (int, float)): + rendered = str(value) + else: + rendered = json.dumps(str(value)) + lines.append(f"{key} = {rendered}") + lines.append("") + path.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8") + return path + + +def update_local_toml(cwd: str | Path, values: dict[str, dict[str, Any]]) -> Path: + local_config = Path(cwd).resolve() / ".ai4math" / "lean_agent.local.toml" + merged = deep_merge(load_toml(local_config), values) + return write_local_toml(cwd, merged) + + +def read_env_local(cwd: str | Path) -> dict[str, str]: + path = Path(cwd).resolve() / ".ai4math" / ".env.local" + if not path.exists(): + return {} + values: dict[str, str] = {} + for raw_line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + try: + parts = shlex.split(line, comments=True, posix=True) + except ValueError: + continue + if parts and parts[0] == "export": + parts = parts[1:] + for part in parts: + if "=" not in part: + continue + key, value = part.split("=", 1) + if ENV_KEY_RE.match(key): + values[key] = value + return values + + +def write_env_local(cwd: str | Path, values: dict[str, str]) -> Path: + ensure_ai4math_gitignore(cwd) + path = Path(cwd).resolve() / ".ai4math" / ".env.local" + invalid = [key for key in values if not ENV_KEY_RE.match(key)] + if invalid: + raise ValueError(f"Invalid environment variable name(s): {', '.join(invalid)}") + + current = path.read_text(encoding="utf-8").splitlines() if path.exists() else [] + keys = set(values) + kept: list[str] = [] + for raw_line in current: + stripped = raw_line.strip() + if not stripped or stripped.startswith("#"): + kept.append(raw_line) + continue + try: + parts = shlex.split(stripped, comments=True, posix=True) + except ValueError: + kept.append(raw_line) + continue + if parts and parts[0] == "export": + parts = parts[1:] + assigned_keys = {part.split("=", 1)[0] for part in parts if "=" in part} + if assigned_keys & keys: + continue + kept.append(raw_line) + + if kept and kept[-1].strip(): + kept.append("") + for key, value in values.items(): + kept.append(f"export {key}={shlex.quote(str(value))}") + path.write_text("\n".join(kept).rstrip() + "\n", encoding="utf-8") + return path + + +def run_command( + command: list[str], + cwd: str | Path | None = None, + timeout: int = 300, + env: dict[str, str] | None = None, +) -> dict[str, Any]: + def to_text(value: Any) -> str: + if value is None: + return "" + if isinstance(value, bytes): + return value.decode("utf-8", errors="replace") + return str(value) + + try: + command_env = None + if env is not None: + command_env = os.environ.copy() + command_env.update(env) + completed = subprocess.run( + command, + cwd=str(cwd) if cwd else None, + env=command_env, + text=True, + capture_output=True, + timeout=timeout, + check=False, + ) + except FileNotFoundError as exc: + return { + "ok": False, + "returncode": 127, + "stdout": "", + "stderr": str(exc), + "command": command, + } + except subprocess.TimeoutExpired as exc: + return { + "ok": False, + "returncode": 124, + "stdout": to_text(exc.stdout), + "stderr": to_text(exc.stderr) or f"Timed out after {timeout}s", + "command": command, + } + return { + "ok": completed.returncode == 0, + "returncode": completed.returncode, + "stdout": to_text(completed.stdout), + "stderr": to_text(completed.stderr), + "command": command, + } + + +def emit_json(result: dict[str, Any], json_output: str | None = None) -> None: + payload = json.dumps(result, ensure_ascii=False, indent=2) + if json_output: + Path(json_output).expanduser().write_text(payload + "\n", encoding="utf-8") + print(payload) + + +def exit_with(result: dict[str, Any], json_output: str | None = None, code: int | None = None) -> None: + emit_json(result, json_output=json_output) + if code is None: + code = 0 if result.get("ok") else 1 + sys.exit(code) + + +def rel_or_abs(path: Path) -> str: + try: + return str(path.relative_to(Path.cwd())) + except ValueError: + return str(path) diff --git a/scripts/configure_lean.py b/scripts/configure_lean.py new file mode 100644 index 0000000..950b148 --- /dev/null +++ b/scripts/configure_lean.py @@ -0,0 +1,185 @@ +from __future__ import annotations + +import shutil +from pathlib import Path +from typing import Any + +from check_lean_project import find_project_root, read_mathlib_revision, read_toolchain +from common import ensure_ai4math_gitignore, expand_path, read_config, run_command, update_local_toml +from tool_status import find_tool + + +def _safe_lake_name(name: str) -> str: + cleaned = "".join(ch if ch.isalnum() or ch == "_" else "_" for ch in name).strip("_") + if not cleaned: + return "lean_workspace" + if cleaned[0].isdigit(): + cleaned = f"lean_{cleaned}" + return cleaned + + +def _lake_command(lake: str, toolchain: str | None, args: list[str]) -> list[str]: + if toolchain and toolchain != "auto": + return [find_tool("elan") or "elan", "run", toolchain, "lake", *args] + return [lake, *args] + + +def _workspace_setup_commands(lake: str, toolchain: str | None, workspace: Path) -> list[list[str]]: + commands: list[list[str]] = [] + if not (workspace / "lake-manifest.json").exists(): + commands.append(_lake_command(lake, toolchain, ["update"])) + commands.extend([ + _lake_command(lake, toolchain, ["exe", "cache", "get"]), + _lake_command(lake, toolchain, ["build"]), + ]) + return commands + + +def _action_failed(action: dict[str, Any]) -> bool: + return not action.get("skipped") and not action.get("recoverable") and not action.get("ok", False) + + +def _workspace_info(path: Path) -> dict[str, Any]: + root = find_project_root(path) + return { + "path": str(path), + "exists": path.exists(), + "project_root": str(root) if root else None, + "toolchain": read_toolchain(root), + "mathlib_revision": read_mathlib_revision(root), + } + + +def inspect_environment(cwd: str | Path = ".", config_path: str | Path | None = None, target: str | Path | None = None) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + config = read_config(cwd_path, config_path) + lean = config.get("lean", {}) + target_path = Path(target).expanduser().resolve() if target else cwd_path + project_root = find_project_root(target_path) + workspace_path = expand_path(lean.get("managed_workspace_path"), cwd_path) or (cwd_path / ".ai4math" / "lean-workspace") + workspace_root = find_project_root(workspace_path) if workspace_path.exists() else None + + missing: list[str] = [] + required_inputs: list[str] = [] + if project_root is None and workspace_root is None: + missing.append("lean_workspace") + required_inputs.append("existing Lake project or permission to create reusable .ai4math/lean-workspace") + + return { + "ok": not missing, + "status": "configured" if not missing else "missing_config", + "configuration_status": "configured" if not missing else "missing_config", + "cwd": str(cwd_path), + "agent": { + "mode": "direct-coding-agent", + "backend": "none", + "numina_required": False, + }, + "lean": { + "target": str(target_path), + "project_root": str(project_root) if project_root else None, + "toolchain": read_toolchain(project_root), + "mathlib_revision": read_mathlib_revision(project_root), + "workspace_path": str(workspace_path), + "workspace_project_root": str(workspace_root) if workspace_root else None, + "workspace_toolchain": read_toolchain(workspace_root), + "workspace_mathlib_revision": read_mathlib_revision(workspace_root), + "workspace_mode": lean.get("workspace_mode", "reuse-managed"), + "align_workspace_versions": bool(lean.get("align_workspace_versions", True)), + }, + "missing_config": missing, + "required_inputs": required_inputs, + "recommended_next_action": "run configure --create-workspace or provide a Lake project" if missing else "ready", + } + + +def configure( + cwd: str | Path = ".", + config_path: str | Path | None = None, + target: str | Path | None = None, + create_workspace: bool = False, + toolchain: str | None = None, + save_local: bool = False, + dry_run: bool = False, +) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + if not dry_run: + ensure_ai4math_gitignore(cwd_path) + + config = read_config(cwd_path, config_path) + lean = config.get("lean", {}) + workspace = expand_path(lean.get("managed_workspace_path"), cwd_path) or (cwd_path / ".ai4math" / "lean-workspace") + workspace_actions: list[dict[str, Any]] = [] + if create_workspace: + lake = find_tool("lake") or "lake" + parent = workspace.parent + lake_project_name = _safe_lake_name(workspace.name) + created_path = parent / lake_project_name + if dry_run: + workspace_actions.append({ + "command": _lake_command(lake, toolchain, ["new", lake_project_name, "math"]), + "cwd": str(parent), + "skipped": True, + "reason": "dry_run", + }) + elif not workspace.exists(): + parent.mkdir(parents=True, exist_ok=True) + created = run_command(_lake_command(lake, toolchain, ["new", lake_project_name, "math"]), cwd=parent) + if not created.get("ok") and find_project_root(created_path): + created["recoverable"] = True + created["recovered_by"] = "lake_project_files_created" + workspace_actions.append(created) + if created.get("ok") or created.get("recoverable"): + if created_path != workspace: + shutil.move(str(created_path), str(workspace)) + workspace_actions.append({ + "ok": True, + "command": ["move", str(created_path), str(workspace)], + "returncode": 0, + "stdout": "", + "stderr": "", + }) + elif find_project_root(workspace): + workspace_actions.append({ + "ok": True, + "command": ["reuse", str(workspace)], + "returncode": 0, + "stdout": "", + "stderr": "", + }) + if not dry_run and find_project_root(workspace): + for command in _workspace_setup_commands(lake, toolchain, workspace): + workspace_actions.append(run_command(command, cwd=workspace, timeout=1800)) + + workspace_info = _workspace_info(workspace) + workspace_failed = create_workspace and not dry_run and ( + not workspace_info["project_root"] or any(_action_failed(action) for action in workspace_actions) + ) + if (save_local or create_workspace) and not dry_run: + update_local_toml(cwd_path, { + "lean": { + "workspace_mode": "reuse-managed", + "managed_workspace_path": str(workspace), + "managed_workspace_root": str(cwd_path / ".ai4math" / "lean-workspaces"), + "reuse_managed_workspace": True, + "workspace_key": "lean-toolchain", + "align_workspace_versions": True, + "preferred_toolchain": toolchain or "auto", + "preferred_mathlib_rev": "auto", + "allow_user_project_version_changes": False, + }, + "agent": { + "mode": "direct-coding-agent", + "backend": "none", + }, + }) + + env = inspect_environment(cwd_path, config_path=config_path, target=target) + env["workspace"] = workspace_info + env["workspace_actions"] = workspace_actions + if workspace_failed: + env["ok"] = False + env["status"] = "lean_workspace_setup_failed" + env["configuration_status"] = "missing_config" + env["recommended_next_action"] = "retry configure --create-workspace after Lean/mathlib download succeeds" + return env diff --git a/scripts/detect_sorry.py b/scripts/detect_sorry.py new file mode 100644 index 0000000..d4256a5 --- /dev/null +++ b/scripts/detect_sorry.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +import re +from pathlib import Path +from typing import Any + + +FORBIDDEN_PATTERNS = { + "sorry": re.compile(r"\bsorry\b"), + "admit": re.compile(r"\badmit\b"), + "axiom": re.compile(r"^\s*axiom\b"), +} + + +def _strip_line_comment(line: str) -> str: + return line.split("--", 1)[0] + + +def scan_text(text: str, source: str = "") -> dict[str, Any]: + findings: list[dict[str, Any]] = [] + for line_no, line in enumerate(text.splitlines(), start=1): + code = _strip_line_comment(line) + for kind, pattern in FORBIDDEN_PATTERNS.items(): + if pattern.search(code): + findings.append({ + "kind": kind, + "file": source, + "line": line_no, + "text": line.rstrip(), + }) + return { + "ok": not findings, + "status": "ok" if not findings else "forbidden_tokens_found", + "findings": findings, + } + + +def scan_file(path: str | Path) -> dict[str, Any]: + file_path = Path(path).expanduser().resolve() + if not file_path.exists(): + return { + "ok": False, + "status": "file_not_found", + "findings": [], + "errors": [{"severity": "error", "data": f"File not found: {file_path}"}], + } + result = scan_text(file_path.read_text(encoding="utf-8", errors="replace"), source=str(file_path)) + result["file"] = str(file_path) + return result diff --git a/scripts/direct_task.py b/scripts/direct_task.py new file mode 100644 index 0000000..6350c04 --- /dev/null +++ b/scripts/direct_task.py @@ -0,0 +1,100 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any + +from check_lean_project import find_project_root, read_mathlib_revision, read_toolchain +from common import expand_path, read_config + + +TASK_TO_PROMPT = { + "prove": "prove_theorem.md", + "formalize": "formalize_statement.md", + "repair": "repair_lean_file.md", + "complete-sorries": "complete_sorries.md", + "batch": "prove_theorem.md", +} + + +def _managed_workspace_root(config: dict[str, Any], cwd_path: Path) -> tuple[Path | None, Path]: + lean = config.get("lean", {}) + workspace_path = expand_path(lean.get("managed_workspace_path"), cwd_path) or (cwd_path / ".ai4math" / "lean-workspace") + workspace_root = find_project_root(workspace_path) if workspace_path.exists() else None + return workspace_root, workspace_path + + +def build_direct_task( + task_type: str, + cwd: str | Path, + target: str | Path, + max_rounds: int = 5, + config_path: str | Path | None = None, + prompt_file: str | Path | None = None, + result_dir: str | Path | None = None, +) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + config = read_config(cwd_path, config_path) + target_path = Path(target).expanduser().resolve() + target_project_root = find_project_root(target_path) + workspace_root, workspace_path = _managed_workspace_root(config, cwd_path) + project_root = target_project_root or workspace_root + workspace_mode = "target_project" if target_project_root else ("managed_workspace" if workspace_root else "missing") + skill_root = Path(__file__).resolve().parents[1] + prompt = Path(prompt_file).expanduser().resolve() if prompt_file else skill_root / "prompts" / TASK_TO_PROMPT.get(task_type, "prove_theorem.md") + + missing = [] + if project_root is None: + missing.append("lean_workspace") + if not target_path.exists() and task_type != "formalize": + missing.append("target") + + next_actions = [ + "Read the target Lean file and identify the exact declaration or error.", + "Run check or lake env lean after each small edit.", + "Keep theorem statements unchanged unless the user explicitly approves a change.", + "Stop when the file verifies without sorry/admit/axiom, or return minimize-failure output.", + ] + if task_type == "formalize": + next_actions.insert(0, "Draft the Lean declaration from the source statement and ask for user confirmation before long proof work.") + if task_type == "complete-sorries": + next_actions.insert(0, "Locate each sorry/admit and solve one minimal target at a time.") + + return { + "ok": not missing, + "status": "direct_task_ready" if not missing else "missing_config", + "agent_mode": "direct-coding-agent", + "backend": "none", + "task_type": task_type, + "target": str(target_path), + "cwd": str(cwd_path), + "project_root": str(project_root) if project_root else None, + "target_project_root": str(target_project_root) if target_project_root else None, + "workspace_project_root": str(workspace_root) if workspace_root else None, + "workspace_path": str(workspace_path), + "workspace_mode": workspace_mode, + "toolchain": read_toolchain(project_root), + "mathlib_revision": read_mathlib_revision(project_root), + "prompt_file": str(prompt), + "result_dir": str(Path(result_dir).expanduser().resolve()) if result_dir else None, + "max_rounds": max_rounds, + "missing_config": missing, + "required_inputs": ["existing Lake project or reusable managed workspace"] if "lean_workspace" in missing else [], + "recommended_next_action": "run configure --create-workspace or move target into a Lake project" if missing else "coding agent should edit/check directly", + "direct_workflow": next_actions, + } + + +def run_direct_task( + task_type: str, + cwd: str | Path, + target: str | Path, + max_rounds: int = 5, + config_path: str | Path | None = None, + prompt_file: str | Path | None = None, + result_dir: str | Path | None = None, + dry_run: bool = False, +) -> dict[str, Any]: + task = build_direct_task(task_type, cwd, target, max_rounds, config_path, prompt_file, result_dir) + if dry_run and task.get("ok"): + task["status"] = "dry_run" + return task diff --git a/scripts/extract_minimal_failure.py b/scripts/extract_minimal_failure.py new file mode 100644 index 0000000..3edd552 --- /dev/null +++ b/scripts/extract_minimal_failure.py @@ -0,0 +1,74 @@ +from __future__ import annotations + +import re +from pathlib import Path +from typing import Any + +from check_lean_project import check_file +from detect_sorry import scan_text + + +DECL_START_RE = re.compile(r"^\s*(theorem|lemma|def|example|instance)\s+") + + +def _line_window(lines: list[str], center: int, radius: int = 8) -> tuple[int, int, str]: + start = max(1, center - radius) + end = min(len(lines), center + radius) + snippet = "\n".join(lines[start - 1:end]) + return start, end, snippet + + +def _target_block(lines: list[str], target: str) -> tuple[int, int, str] | None: + start_index = None + for index, line in enumerate(lines): + if re.search(rf"\b{re.escape(target)}\b", line) and DECL_START_RE.search(line): + start_index = index + break + if start_index is None: + return None + end_index = len(lines) + for index in range(start_index + 1, len(lines)): + if DECL_START_RE.search(lines[index]): + end_index = index + break + return start_index + 1, end_index, "\n".join(lines[start_index:end_index]) + + +def extract(file: str | Path, target: str | None = None, run_lean: bool = False, timeout: int = 120) -> dict[str, Any]: + file_path = Path(file).expanduser().resolve() + if not file_path.exists(): + return { + "ok": False, + "status": "file_not_found", + "minimal_failure": {}, + "errors": [{"severity": "error", "data": f"File not found: {file_path}"}], + } + text = file_path.read_text(encoding="utf-8", errors="replace") + lines = text.splitlines() + block = _target_block(lines, target) if target else None + if block is None: + scan = scan_text(text, source=str(file_path)) + if scan.get("findings"): + first = scan["findings"][0] + block = _line_window(lines, int(first["line"])) + else: + block = (1, min(len(lines), 40), "\n".join(lines[:40])) + + lean_result = check_file(file_path, timeout=timeout) if run_lean else None + start, end, snippet = block + status = "minimal_failure_extracted" + ok = True + if lean_result and not lean_result.get("ok"): + status = "lean_failure_minimized" + return { + "ok": ok, + "status": status, + "file": str(file_path), + "target": target, + "minimal_failure": { + "start_line": start, + "end_line": end, + "snippet": snippet, + "lean": lean_result, + }, + } diff --git a/scripts/tool_status.py b/scripts/tool_status.py new file mode 100644 index 0000000..512464d --- /dev/null +++ b/scripts/tool_status.py @@ -0,0 +1,79 @@ +from __future__ import annotations + +import shutil +from pathlib import Path +from typing import Any + +from common import run_command + + +DEFAULT_TOOLS = ["git", "python3", "elan", "lean", "lake"] +EXTRA_BIN_DIRS = [ + Path.home() / ".elan" / "bin", + Path.home() / ".local" / "bin", + Path.home() / ".cargo" / "bin", +] + + +def find_tool(name: str) -> str | None: + found = shutil.which(name) + if found: + return found + for directory in EXTRA_BIN_DIRS: + candidate = directory / name + if candidate.exists() and candidate.is_file(): + return str(candidate) + return None + + +def tool_versions(names: list[str] | None = None) -> dict[str, Any]: + tools: dict[str, Any] = {} + for name in names or DEFAULT_TOOLS: + path = find_tool(name) + info: dict[str, Any] = {"path": path, "available": bool(path)} + if path: + if name in {"lean", "lake"} and ".elan/bin" in path: + info["version_ok"] = None + info["version"] = [] + info["version_note"] = "skipped to avoid implicit elan toolchain download" + tools[name] = info + continue + version = run_command([path, "--version"], timeout=20) + info["version_ok"] = bool(version.get("ok")) + info["version"] = (version.get("stdout") or version.get("stderr") or "").strip().splitlines()[:3] + tools[name] = info + return tools + + +def doctor(cwd: str | Path = ".") -> dict[str, Any]: + tools = tool_versions() + missing = [name for name, info in tools.items() if not info["available"]] + missing_for_lean_workspace = [name for name in ("lake",) if not tools[name]["available"]] + missing_for_clone = [name for name in ("git",) if not tools[name]["available"]] + return { + "ok": True, + "status": "reported", + "cwd": str(Path(cwd).resolve()), + "tools": tools, + "missing_tools": missing, + "readiness": { + "can_create_lean_workspace": not missing_for_lean_workspace, + "missing_for_lean_workspace": missing_for_lean_workspace, + "missing_for_clone": missing_for_clone, + }, + "recommended_next_action": _recommend( + missing_for_clone, + missing_for_lean_workspace, + ), + } + + +def _recommend( + missing_clone: list[str], + missing_lean: list[str], +) -> str: + if missing_clone: + return "install git before using Lake projects with remote dependencies" + if missing_lean: + return "install Lean/elan before creating the reusable Lean workspace" + return "ready for direct Lean coding-agent workflow" diff --git a/scripts/validate_patch.py b/scripts/validate_patch.py new file mode 100644 index 0000000..2414007 --- /dev/null +++ b/scripts/validate_patch.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +import difflib +import re +from pathlib import Path +from typing import Any + +from detect_sorry import scan_text + + +DECL_RE = re.compile(r"^\s*(theorem|lemma|def|class|structure|inductive)\s+([A-Za-z_][\w'.]*)\b(.*)") + + +def collect_declarations(text: str) -> dict[str, str]: + declarations: dict[str, str] = {} + for line in text.splitlines(): + match = DECL_RE.match(line) + if not match: + continue + kind, name, rest = match.groups() + header = f"{kind} {name} {rest}".split(":=", 1)[0].strip() + declarations[name] = re.sub(r"\s+", " ", header) + return declarations + + +def review_patch(before_text: str, after_text: str, allow_statement_changes: bool = False) -> dict[str, Any]: + after_scan = scan_text(after_text, source="after") + before_decls = collect_declarations(before_text) + after_decls = collect_declarations(after_text) + statement_changes = [] + for name, before_header in before_decls.items(): + after_header = after_decls.get(name) + if after_header and before_header != after_header: + statement_changes.append({ + "declaration": name, + "before": before_header, + "after": after_header, + }) + + findings: list[dict[str, Any]] = [] + findings.extend(after_scan.get("findings", [])) + if statement_changes and not allow_statement_changes: + findings.append({ + "kind": "statement_changed", + "changes": statement_changes, + }) + + return { + "ok": not findings, + "status": "ok" if not findings else "patch_safety_violation", + "forbidden_findings": after_scan.get("findings", []), + "statement_changes": statement_changes, + "diff": "\n".join(difflib.unified_diff( + before_text.splitlines(), + after_text.splitlines(), + fromfile="before", + tofile="after", + lineterm="", + )), + "findings": findings, + } + + +def review_files(before: str | Path, after: str | Path, allow_statement_changes: bool = False) -> dict[str, Any]: + before_path = Path(before).expanduser().resolve() + after_path = Path(after).expanduser().resolve() + if not before_path.exists() or not after_path.exists(): + missing = [str(path) for path in (before_path, after_path) if not path.exists()] + return { + "ok": False, + "status": "file_not_found", + "errors": [{"severity": "error", "data": f"Missing files: {', '.join(missing)}"}], + } + result = review_patch( + before_path.read_text(encoding="utf-8", errors="replace"), + after_path.read_text(encoding="utf-8", errors="replace"), + allow_statement_changes=allow_statement_changes, + ) + result["before"] = str(before_path) + result["after"] = str(after_path) + return result diff --git a/scripts/verify_delivery.py b/scripts/verify_delivery.py new file mode 100644 index 0000000..5f56a8a --- /dev/null +++ b/scripts/verify_delivery.py @@ -0,0 +1,244 @@ +from __future__ import annotations + +import argparse +import json +import sys +import tempfile +from pathlib import Path +from typing import Any + +from check_lean_project import check_project +from common import run_command +from configure_lean import inspect_environment +from direct_task import run_direct_task +from extract_minimal_failure import extract +from tool_status import doctor, find_tool +from validate_patch import review_files + + +SKILL_ROOT = Path(__file__).resolve().parents[1] +REQUIRED_FILES = [ + "SKILL.md", + "agents/openai.yaml", + "config/lean_agent.example.toml", + "schemas/task.schema.json", + "schemas/result.schema.json", + "schemas/config.schema.json", + "references/lean_runtime_configuration.md", + "references/interactive_orchestration.md", + "references/direct_lean_workflow.md", + "references/review_checklist.md", + "references/failure_taxonomy.md", + "references/numina_reverse_analysis.md", + "scripts/ai4m_lean.py", + "scripts/configure_lean.py", + "scripts/direct_task.py", + "scripts/validate_patch.py", + "scripts/extract_minimal_failure.py", +] +REQUIRED_COMMANDS = { + "env", + "doctor", + "configure", + "check", + "prove", + "formalize", + "repair", + "complete-sorries", + "batch", + "review", + "detect-sorry", + "minimize-failure", + "verify-delivery", +} + + +def _parser_commands() -> set[str]: + from ai4m_lean import build_parser + + parser = build_parser() + for action in parser._actions: + if isinstance(action, argparse._SubParsersAction): + return set(action.choices) + return set() + + +def _load_schema(path: Path) -> dict[str, Any]: + return json.loads(path.read_text(encoding="utf-8")) + + +def _package_hygiene() -> dict[str, Any]: + generated = [ + str(path.relative_to(SKILL_ROOT)) + for path in SKILL_ROOT.rglob("*") + if "__pycache__" in path.parts or path.suffix == ".pyc" + ] + suspicious_secret_patterns = [ + "sk-" + "ant-", + "sk-" + "proj-", + "BEGIN " + "OPENAI API KEY", + ] + secret_hits: list[str] = [] + for path in SKILL_ROOT.rglob("*"): + if not path.is_file() or "__pycache__" in path.parts or path.suffix == ".pyc": + continue + try: + text = path.read_text(encoding="utf-8", errors="replace") + except OSError: + continue + if any(pattern in text for pattern in suspicious_secret_patterns): + secret_hits.append(str(path.relative_to(SKILL_ROOT))) + return { + "ok": not secret_hits, + "generated_files": generated, + "generated_files_note": "ignored by .gitignore; remove before packaging if creating an archive" if generated else None, + "secret_pattern_hits": secret_hits, + } + + +def _guidance_first_check() -> dict[str, Any]: + text = (SKILL_ROOT / "SKILL.md").read_text(encoding="utf-8", errors="replace") + required_phrases = [ + "## Agent Playbook", + "## Helper Toolbox", + "The bundled CLI is a helper toolbox, not the workflow driver.", + "Do not let helper command availability override a better direct coding-agent path.", + ] + missing = [phrase for phrase in required_phrases if phrase not in text] + return { + "ok": not missing and "## Commands" not in text, + "missing_phrases": missing, + "commands_section_present": "## Commands" in text, + } + + +def verify( + cwd: str | Path = ".", + require_environment: bool = False, + include_workspace_build: bool = False, + run_tests: bool = False, +) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + files = [{"path": item, "exists": (SKILL_ROOT / item).exists()} for item in REQUIRED_FILES] + commands = _parser_commands() + schemas = [] + for name in ("task.schema.json", "result.schema.json", "config.schema.json"): + path = SKILL_ROOT / "schemas" / name + try: + _load_schema(path) + schemas.append({"path": f"schemas/{name}", "ok": True}) + except Exception as exc: # noqa: BLE001 - report schema parse failure in JSON + schemas.append({"path": f"schemas/{name}", "ok": False, "error": str(exc)}) + + fixtures = SKILL_ROOT / "tests" / "fixtures" + with tempfile.TemporaryDirectory() as tmp: + dry_root = Path(tmp) + dry_target = dry_root / "Failure.lean" + (dry_root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (dry_root / "lakefile.toml").write_text('name = "verify_delivery"\n', encoding="utf-8") + dry_target.write_text((fixtures / "failure.lean").read_text(encoding="utf-8"), encoding="utf-8") + dry_run = run_direct_task("prove", dry_root, dry_target, dry_run=True) + review = review_files(fixtures / "before.lean", fixtures / "after_bad.lean") + failure = extract(fixtures / "failure.lean", target=None, run_lean=False) + + tool_report = doctor(cwd_path) if require_environment else None + env_report = inspect_environment(cwd_path) if require_environment else None + workspace_check = None + workspace_build = None + if include_workspace_build: + env_for_workspace = env_report or inspect_environment(cwd_path) + workspace_root = env_for_workspace.get("lean", {}).get("workspace_project_root") + if workspace_root: + workspace_check = check_project(workspace_root, skip_build=True) + lake = find_tool("lake") or "lake" + workspace_build = run_command([lake, "build"], cwd=workspace_root, timeout=1800) + else: + workspace_check = {"ok": False, "status": "missing_workspace"} + + tests = None + if run_tests: + tests = run_command([sys.executable, "-m", "unittest", "discover", "-s", str(SKILL_ROOT / "tests")], cwd=SKILL_ROOT, timeout=300) + + hygiene = _package_hygiene() + guidance_first = _guidance_first_check() + checks = { + "required_files": all(item["exists"] for item in files), + "required_commands": REQUIRED_COMMANDS.issubset(commands), + "schemas": all(item["ok"] for item in schemas), + "guidance_first_skill": bool(guidance_first.get("ok")), + "dry_run_prove": bool(dry_run.get("ok") and dry_run.get("status") == "dry_run"), + "patch_guard": bool(not review.get("ok") and review.get("findings")), + "minimal_failure": bool(failure.get("ok") and failure.get("minimal_failure", {}).get("snippet")), + "package_hygiene": bool(hygiene.get("ok")), + } + if require_environment: + checks["tool_environment"] = bool(tool_report and tool_report.get("ok")) + checks["lean_agent_environment"] = bool(env_report and env_report.get("ok")) + if include_workspace_build: + checks["workspace_check"] = bool(workspace_check and workspace_check.get("ok")) + checks["workspace_build"] = bool(workspace_build and workspace_build.get("ok")) + if run_tests: + checks["unit_tests"] = bool(tests and tests.get("ok")) + + ok = all(checks.values()) + return { + "ok": ok, + "status": "delivery_ready" if ok else "delivery_blocked", + "cwd": str(cwd_path), + "skill_root": str(SKILL_ROOT), + "checks": checks, + "files": files, + "commands": { + "required": sorted(REQUIRED_COMMANDS), + "available": sorted(commands), + "missing": sorted(REQUIRED_COMMANDS - commands), + }, + "schemas": schemas, + "guidance_first_skill": guidance_first, + "dry_run_prove": { + "ok": dry_run.get("ok"), + "status": dry_run.get("status"), + "backend": dry_run.get("backend"), + "agent_mode": dry_run.get("agent_mode"), + "missing_config": dry_run.get("missing_config"), + }, + "patch_guard": { + "ok": review.get("ok"), + "status": review.get("status"), + "finding_count": len(review.get("findings", [])), + }, + "minimal_failure": { + "ok": failure.get("ok"), + "status": failure.get("status"), + "start_line": failure.get("minimal_failure", {}).get("start_line"), + "end_line": failure.get("minimal_failure", {}).get("end_line"), + }, + "hygiene": hygiene, + "tool_environment": tool_report, + "lean_agent_environment": env_report, + "workspace_check": workspace_check, + "workspace_build": workspace_build, + "unit_tests": tests, + "external_api_note": "This direct workflow does not call Numina or external model APIs; the coding agent edits and checks Lean locally.", + } + + +def main(argv: list[str] | None = None) -> None: + parser = argparse.ArgumentParser(description="Verify AI4Math Lean Agents delivery readiness") + parser.add_argument("--cwd", default=".") + parser.add_argument("--require-environment", action="store_true") + parser.add_argument("--include-workspace-build", action="store_true") + parser.add_argument("--run-tests", action="store_true") + args = parser.parse_args(argv) + result = verify( + cwd=args.cwd, + require_environment=args.require_environment, + include_workspace_build=args.include_workspace_build, + run_tests=args.run_tests, + ) + print(json.dumps(result, indent=2, ensure_ascii=False)) + raise SystemExit(0 if result.get("ok") else 1) + + +if __name__ == "__main__": + main() diff --git a/tests/fixtures/after_bad.lean b/tests/fixtures/after_bad.lean new file mode 100644 index 0000000..293bc7c --- /dev/null +++ b/tests/fixtures/after_bad.lean @@ -0,0 +1,4 @@ +import Mathlib + +theorem add_zero_nat (n : Nat) : n + 0 = n := by + sorry diff --git a/tests/fixtures/after_statement_changed.lean b/tests/fixtures/after_statement_changed.lean new file mode 100644 index 0000000..36380e2 --- /dev/null +++ b/tests/fixtures/after_statement_changed.lean @@ -0,0 +1,4 @@ +import Mathlib + +theorem add_zero_nat (n : Nat) : n + 0 = n + 0 := by + rfl diff --git a/tests/fixtures/before.lean b/tests/fixtures/before.lean new file mode 100644 index 0000000..4f7c62a --- /dev/null +++ b/tests/fixtures/before.lean @@ -0,0 +1,4 @@ +import Mathlib + +theorem add_zero_nat (n : Nat) : n + 0 = n := by + exact Nat.add_zero n diff --git a/tests/fixtures/failure.lean b/tests/fixtures/failure.lean new file mode 100644 index 0000000..490be67 --- /dev/null +++ b/tests/fixtures/failure.lean @@ -0,0 +1,7 @@ +import Mathlib + +theorem target_theorem (n : Nat) : n + 0 = n := by + sorry + +theorem other_theorem (n : Nat) : 0 + n = n := by + exact Nat.zero_add n diff --git a/tests/test_check_lean_project.py b/tests/test_check_lean_project.py new file mode 100644 index 0000000..7d04185 --- /dev/null +++ b/tests/test_check_lean_project.py @@ -0,0 +1,59 @@ +from __future__ import annotations + +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +SCRIPT_DIR = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPT_DIR)) + +from check_lean_project import check_project, find_project_root, read_mathlib_revision, read_toolchain # noqa: E402 + + +class CheckLeanProjectTests(unittest.TestCase): + def test_finds_project_root_and_versions(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = (Path(tmp) / "proj").resolve() + nested = root / "A" / "B" + nested.mkdir(parents=True) + (root / "lean-toolchain").write_text("leanprover/lean4:v4.26.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text( + 'name = "proj"\n\n[[require]]\nname = "mathlib"\nscope = "leanprover-community"\nrev = "v4.26.0"\n', + encoding="utf-8", + ) + target = nested / "T.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + + self.assertEqual(find_project_root(target), root) + self.assertEqual(read_toolchain(root), "leanprover/lean4:v4.26.0") + self.assertEqual(read_mathlib_revision(root), "v4.26.0") + + result = check_project(root, skip_build=True) + self.assertTrue(result["ok"]) + self.assertEqual(result["status"], "ok_skip_build") + + def test_build_uses_discovered_lake_binary(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + + with patch("check_lean_project.find_tool", return_value="/custom/bin/lake"), \ + patch("check_lean_project.run_command", return_value={ + "ok": True, + "returncode": 0, + "stdout": "", + "stderr": "", + "command": ["/custom/bin/lake", "build"], + }) as run: + result = check_project(root) + + self.assertTrue(result["ok"]) + run.assert_called_once() + self.assertEqual(run.call_args.args[0], ["/custom/bin/lake", "build"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..3339b2e --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,103 @@ +from __future__ import annotations + +import json +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + +SKILL_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(SKILL_ROOT / "scripts")) + +from ai4m_lean import EXIT_LEAN_FAILED, _exit_code # noqa: E402 + +CLI = SKILL_ROOT / "scripts" / "ai4m_lean.py" +FIXTURES = Path(__file__).resolve().parent / "fixtures" + + +class CliTests(unittest.TestCase): + def test_dry_run_prove_outputs_direct_task(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + workspace = root / ".ai4math" / "lean-workspace" + workspace.mkdir(parents=True) + (workspace / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (workspace / "lakefile.toml").write_text('name = "lean_workspace"\n', encoding="utf-8") + target = root / "Failure.lean" + target.write_text((FIXTURES / "failure.lean").read_text(encoding="utf-8"), encoding="utf-8") + + result = subprocess.run( + [ + sys.executable, + str(CLI), + "prove", + "--cwd", + str(root), + "--file", + str(target), + "--dry-run", + ], + text=True, + capture_output=True, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertEqual(payload["status"], "dry_run") + self.assertEqual(payload["agent_mode"], "direct-coding-agent") + self.assertEqual(payload["backend"], "none") + self.assertIn("direct_workflow", payload) + self.assertNotIn("command", payload) + + def test_check_skip_build_outputs_json(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / "lean-toolchain").write_text("leanprover/lean4:v4.26.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + result = subprocess.run( + [sys.executable, str(CLI), "check", "--cwd", str(root), "--skip-build"], + text=True, + capture_output=True, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertTrue(payload["ok"]) + self.assertEqual(payload["toolchain"], "leanprover/lean4:v4.26.0") + + def test_doctor_outputs_tool_report(self) -> None: + result = subprocess.run( + [sys.executable, str(CLI), "doctor", "--cwd", str(SKILL_ROOT)], + text=True, + capture_output=True, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertTrue(payload["ok"]) + self.assertIn("tools", payload) + self.assertIn("readiness", payload) + + def test_lean_workspace_deploy_failure_uses_lean_exit_code(self) -> None: + self.assertEqual( + _exit_code({"ok": False, "status": "lean_workspace_setup_failed"}), + EXIT_LEAN_FAILED, + ) + + def test_verify_delivery_package_checks(self) -> None: + result = subprocess.run( + [sys.executable, str(CLI), "verify-delivery", "--cwd", str(SKILL_ROOT)], + text=True, + capture_output=True, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertTrue(payload["ok"]) + self.assertEqual(payload["status"], "delivery_ready") + self.assertIn("verify-delivery", payload["commands"]["available"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_common_config.py b/tests/test_common_config.py new file mode 100644 index 0000000..b1951b5 --- /dev/null +++ b/tests/test_common_config.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPTS)) + +from common import expand_path, load_toml, read_env_local, write_env_local # noqa: E402 + + +class CommonConfigTests(unittest.TestCase): + def test_load_toml_has_python39_fallback(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + path = Path(tmp) / "config.toml" + path.write_text( + '[agent]\nmode = "direct-coding-agent"\nbackend = "none"\n' + '[lean]\nreuse_managed_workspace = true\n', + encoding="utf-8", + ) + with patch("common.tomllib", None): + data = load_toml(path) + + self.assertEqual(data["agent"]["backend"], "none") + self.assertTrue(data["lean"]["reuse_managed_workspace"]) + + def test_expand_path_preserves_symlink_text(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + real = root / "real-python" + link = root / "venv-python" + real.touch() + link.symlink_to(real) + + self.assertEqual(expand_path(str(link), root), link) + + def test_write_env_local_updates_values_and_is_ignored(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + + write_env_local(root, {"AI4MATH_SAMPLE_TOKEN": "secret one"}) + write_env_local(root, {"AI4MATH_SAMPLE_TOKEN": "secret two", "AI4MATH_SAMPLE_MODE": "local"}) + + env = read_env_local(root) + self.assertEqual(env["AI4MATH_SAMPLE_TOKEN"], "secret two") + self.assertEqual(env["AI4MATH_SAMPLE_MODE"], "local") + self.assertEqual((root / ".ai4math" / ".env.local").read_text().count("AI4MATH_SAMPLE_TOKEN"), 1) + self.assertIn(".env.local", (root / ".ai4math" / ".gitignore").read_text()) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_configure_lean.py b/tests/test_configure_lean.py new file mode 100644 index 0000000..e53cf2b --- /dev/null +++ b/tests/test_configure_lean.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPTS)) + +from common import load_toml # noqa: E402 +from configure_lean import configure, inspect_environment # noqa: E402 + + +class ConfigureLeanTests(unittest.TestCase): + def test_existing_lean_project_is_direct_agent_ready(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + target = root / "Main.lean" + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + target.write_text("example : True := by trivial\n", encoding="utf-8") + + result = inspect_environment(root, target=target) + + self.assertTrue(result["ok"]) + self.assertEqual(result["agent"]["mode"], "direct-coding-agent") + self.assertEqual(result["agent"]["backend"], "none") + self.assertFalse(result["agent"]["numina_required"]) + self.assertEqual(result["missing_config"], []) + + def test_save_local_writes_lean_agent_config(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + + result = configure(root, save_local=True, toolchain="leanprover/lean4:v4.28.0") + local = load_toml(root / ".ai4math" / "lean_agent.local.toml") + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "missing_config") + self.assertEqual(local["agent"]["backend"], "none") + self.assertEqual(local["agent"]["mode"], "direct-coding-agent") + self.assertEqual(local["lean"]["preferred_toolchain"], "leanprover/lean4:v4.28.0") + self.assertIn("lean_agent.local.toml", (root / ".ai4math" / ".gitignore").read_text()) + + def test_workspace_creation_failure_is_reported_as_lean_setup_failure(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + + with patch("configure_lean.find_tool", return_value="/usr/bin/lake"), \ + patch("configure_lean.run_command", return_value={ + "ok": False, + "returncode": 1, + "stdout": "", + "stderr": "download failed", + "command": ["/usr/bin/lake", "new", "lean_workspace", "math"], + }): + result = configure(root, create_workspace=True) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "lean_workspace_setup_failed") + self.assertIn("retry configure --create-workspace", result["recommended_next_action"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_detect_sorry.py b/tests/test_detect_sorry.py new file mode 100644 index 0000000..2bcd114 --- /dev/null +++ b/tests/test_detect_sorry.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +import sys +import unittest +from pathlib import Path + +SCRIPT_DIR = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPT_DIR)) + +from detect_sorry import scan_text # noqa: E402 + + +class DetectSorryTests(unittest.TestCase): + def test_detects_sorry_and_ignores_line_comment(self) -> None: + result = scan_text("theorem t : True := by\n trivial\n-- sorry\n", source="x.lean") + self.assertTrue(result["ok"]) + + result = scan_text("theorem t : True := by\n sorry\n", source="x.lean") + self.assertFalse(result["ok"]) + self.assertEqual(result["findings"][0]["kind"], "sorry") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_direct_task.py b/tests/test_direct_task.py new file mode 100644 index 0000000..b6f6363 --- /dev/null +++ b/tests/test_direct_task.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import sys +import tempfile +import unittest +from pathlib import Path + +SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPTS)) + +from direct_task import build_direct_task, run_direct_task # noqa: E402 + + +class DirectTaskTests(unittest.TestCase): + def test_managed_workspace_routes_standalone_file_without_backend(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + workspace = root / ".ai4math" / "lean-workspace" + workspace.mkdir(parents=True) + (workspace / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (workspace / "lakefile.toml").write_text('name = "lean_workspace"\n', encoding="utf-8") + target = root / "Standalone.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + + result = build_direct_task("prove", root, target) + + self.assertTrue(result["ok"]) + self.assertEqual(result["status"], "direct_task_ready") + self.assertEqual(result["agent_mode"], "direct-coding-agent") + self.assertEqual(result["backend"], "none") + self.assertEqual(result["workspace_mode"], "managed_workspace") + self.assertEqual(result["missing_config"], []) + + def test_missing_workspace_reports_required_input(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + target = root / "Standalone.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + + result = build_direct_task("prove", root, target) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "missing_config") + self.assertIn("lean_workspace", result["missing_config"]) + self.assertEqual(result["backend"], "none") + + def test_dry_run_marks_ready_task_without_external_command(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + target = root / "Main.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + + result = run_direct_task("repair", root, target, dry_run=True) + + self.assertTrue(result["ok"]) + self.assertEqual(result["status"], "dry_run") + self.assertEqual(result["backend"], "none") + self.assertNotIn("command", result) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_validate_patch.py b/tests/test_validate_patch.py new file mode 100644 index 0000000..fc2a130 --- /dev/null +++ b/tests/test_validate_patch.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +import sys +import unittest +from pathlib import Path + +SCRIPT_DIR = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPT_DIR)) + +from validate_patch import review_files # noqa: E402 + + +FIXTURES = Path(__file__).resolve().parent / "fixtures" + + +class ValidatePatchTests(unittest.TestCase): + def test_rejects_sorry(self) -> None: + result = review_files(FIXTURES / "before.lean", FIXTURES / "after_bad.lean") + self.assertFalse(result["ok"]) + self.assertTrue(result["forbidden_findings"]) + + def test_rejects_statement_change(self) -> None: + result = review_files(FIXTURES / "before.lean", FIXTURES / "after_statement_changed.lean") + self.assertFalse(result["ok"]) + self.assertTrue(result["statement_changes"]) + + +if __name__ == "__main__": + unittest.main() From 44dcaa54b017fda93000cfa91a42474e9d6d4f12 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 22 May 2026 17:09:23 +0800 Subject: [PATCH 02/37] Restructure skill repository layout --- .codex/skills/ai4math-lean-agents/SKILL.md | 14 ++++ .cursor/rules/ai4math-lean-agents.mdc | 14 ++++ .github/workflows/verify.yml | 23 ++++++ .gitignore | 15 ++++ .opencode/agents/ai4math-lean-agents.md | 17 ++++ AGENTS.md | 17 ++++ CLAUDE.md | 11 +++ GEMINI.md | 11 +++ README.md | 81 +++++++++++++++++++ .../AI4Math-Lean-Agents/SKILL.md | 0 .../AI4Math-Lean-Agents/agents}/openai.yaml | 0 .../AI4Math-Lean-Agents/config}/env.example | 0 .../config}/lean_agent.example.toml | 0 .../prompts}/complete_sorries.md | 0 .../prompts}/formalize_statement.md | 0 .../prompts}/prove_theorem.md | 0 .../prompts}/repair_lean_file.md | 0 .../references}/direct_lean_workflow.md | 0 .../references}/failure_taxonomy.md | 0 .../references}/interactive_orchestration.md | 0 .../references}/lean_runtime_configuration.md | 0 .../references}/numina_reverse_analysis.md | 0 .../references}/review_checklist.md | 0 .../schemas}/config.schema.json | 0 .../schemas}/result.schema.json | 0 .../schemas}/task.schema.json | 0 .../AI4Math-Lean-Agents/scripts}/ai4m_lean.py | 0 .../scripts}/check_lean_project.py | 0 .../AI4Math-Lean-Agents/scripts}/common.py | 0 .../scripts}/configure_lean.py | 0 .../scripts}/detect_sorry.py | 0 .../scripts}/direct_task.py | 0 .../scripts}/extract_minimal_failure.py | 0 .../scripts}/tool_status.py | 0 .../scripts}/validate_patch.py | 0 .../scripts}/verify_delivery.py | 0 .../tests}/fixtures/after_bad.lean | 0 .../fixtures/after_statement_changed.lean | 0 .../tests}/fixtures/before.lean | 0 .../tests}/fixtures/failure.lean | 0 .../tests}/test_check_lean_project.py | 0 .../AI4Math-Lean-Agents/tests}/test_cli.py | 0 .../tests}/test_common_config.py | 0 .../tests}/test_configure_lean.py | 0 .../tests}/test_detect_sorry.py | 0 .../tests}/test_direct_task.py | 0 .../tests}/test_validate_patch.py | 0 47 files changed, 203 insertions(+) create mode 100644 .codex/skills/ai4math-lean-agents/SKILL.md create mode 100644 .cursor/rules/ai4math-lean-agents.mdc create mode 100644 .github/workflows/verify.yml create mode 100644 .gitignore create mode 100644 .opencode/agents/ai4math-lean-agents.md create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 GEMINI.md create mode 100644 README.md rename SKILL.md => skills/AI4Math-Lean-Agents/SKILL.md (100%) rename {agents => skills/AI4Math-Lean-Agents/agents}/openai.yaml (100%) rename {config => skills/AI4Math-Lean-Agents/config}/env.example (100%) rename {config => skills/AI4Math-Lean-Agents/config}/lean_agent.example.toml (100%) rename {prompts => skills/AI4Math-Lean-Agents/prompts}/complete_sorries.md (100%) rename {prompts => skills/AI4Math-Lean-Agents/prompts}/formalize_statement.md (100%) rename {prompts => skills/AI4Math-Lean-Agents/prompts}/prove_theorem.md (100%) rename {prompts => skills/AI4Math-Lean-Agents/prompts}/repair_lean_file.md (100%) rename {references => skills/AI4Math-Lean-Agents/references}/direct_lean_workflow.md (100%) rename {references => skills/AI4Math-Lean-Agents/references}/failure_taxonomy.md (100%) rename {references => skills/AI4Math-Lean-Agents/references}/interactive_orchestration.md (100%) rename {references => skills/AI4Math-Lean-Agents/references}/lean_runtime_configuration.md (100%) rename {references => skills/AI4Math-Lean-Agents/references}/numina_reverse_analysis.md (100%) rename {references => skills/AI4Math-Lean-Agents/references}/review_checklist.md (100%) rename {schemas => skills/AI4Math-Lean-Agents/schemas}/config.schema.json (100%) rename {schemas => skills/AI4Math-Lean-Agents/schemas}/result.schema.json (100%) rename {schemas => skills/AI4Math-Lean-Agents/schemas}/task.schema.json (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/ai4m_lean.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/check_lean_project.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/common.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/configure_lean.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/detect_sorry.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/direct_task.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/extract_minimal_failure.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/tool_status.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/validate_patch.py (100%) rename {scripts => skills/AI4Math-Lean-Agents/scripts}/verify_delivery.py (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/fixtures/after_bad.lean (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/fixtures/after_statement_changed.lean (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/fixtures/before.lean (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/fixtures/failure.lean (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/test_check_lean_project.py (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/test_cli.py (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/test_common_config.py (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/test_configure_lean.py (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/test_detect_sorry.py (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/test_direct_task.py (100%) rename {tests => skills/AI4Math-Lean-Agents/tests}/test_validate_patch.py (100%) diff --git a/.codex/skills/ai4math-lean-agents/SKILL.md b/.codex/skills/ai4math-lean-agents/SKILL.md new file mode 100644 index 0000000..9334e3a --- /dev/null +++ b/.codex/skills/ai4math-lean-agents/SKILL.md @@ -0,0 +1,14 @@ +--- +name: ai4math-lean-agents +description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, theorem formalization, sorry completion, patch review, and minimal failure handoff. +--- + +# AI4Math Lean Agents Repo Shim + +This repo-local shim points to the canonical skill: + +```text +../../../skills/AI4Math-Lean-Agents/SKILL.md +``` + +Read that file and follow it as the source of truth. The coding agent should directly operate Lean; helper CLI commands are guardrails, not a proof backend. diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc new file mode 100644 index 0000000..7acbc4a --- /dev/null +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -0,0 +1,14 @@ +--- +description: AI4Math Lean Agents workflow for Lean 4 formalization and proof repair +globs: + - "**/*.lean" + - "**/lakefile.*" + - "**/lean-toolchain" +alwaysApply: false +--- + +Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. + +The coding agent directly edits Lean and validates with Lean/Lake. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, patch review, `sorry` detection, or minimal failure handoff. + +Do not deploy Numina or require external model API keys for this workflow. diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 0000000..3a21578 --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,23 @@ +name: Verify AI4Math Lean Agents + +on: + push: + pull_request: + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Run unit tests + run: | + PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/AI4Math-Lean-Agents/tests + + - name: Verify package shape + run: | + PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d4f8a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +.DS_Store +__pycache__/ +*.py[cod] +.pytest_cache/ +.mypy_cache/ + +.ai4math/ +.env +.env.local + +*.olean +*.ilean +*.trace +build/ +.lake/ diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md new file mode 100644 index 0000000..7b17cc8 --- /dev/null +++ b/.opencode/agents/ai4math-lean-agents.md @@ -0,0 +1,17 @@ +# AI4Math Lean Agents + +Use this agent for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, and minimal failure handoff. + +Canonical workflow: + +```text +skills/AI4Math-Lean-Agents/SKILL.md +``` + +Rules: + +- Directly inspect and edit Lean files. +- Validate with Lean/Lake after meaningful edits. +- Use helper CLI commands only as deterministic guardrails. +- Do not use Numina or external model APIs as a backend. +- Preserve theorem statements unless the user explicitly approves a change. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a3a2b1f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,17 @@ +# Agent Instructions + +Use the canonical skill at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, and minimal failure handoff. + +Core rules: + +- The coding agent directly operates Lean; do not treat helper CLI commands as a proof backend. +- Do not deploy or call Numina, Claude Code CLI, or external model APIs for this skill. +- Prefer the user's existing Lake project. Use `.ai4math/lean-workspace` only when a standalone file needs project context. +- Preserve theorem statements unless the user explicitly approves a change. +- Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. + +Useful validation: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +``` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ce951ef --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,11 @@ +# Claude Code Instructions + +For Lean work in this repository, read and follow: + +```text +skills/AI4Math-Lean-Agents/SKILL.md +``` + +Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run Lean/Lake checks frequently, and use the helper CLI only for deterministic checks such as environment inspection, patch review, `sorry` detection, and minimal failure extraction. + +Do not deploy Numina or require API keys for this workflow. diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..af612dc --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,11 @@ +# Gemini Instructions + +For Lean 4 formal verification tasks, use the skill instructions at: + +```text +skills/AI4Math-Lean-Agents/SKILL.md +``` + +The agent should directly inspect and edit Lean files, validate with Lean/Lake, preserve theorem statements, and avoid final patches with `sorry`, `admit`, or new `axiom`. + +The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a3b2477 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# AI4Math Lean Agents + +AI4Math Lean Agents is a guidance-first Codex skill for Lean 4 formal verification. The active coding agent directly reads, edits, and checks Lean code; the bundled CLI is only a deterministic helper toolbox for environment checks, Lean validation, patch review, and minimal failure handoff. + +The canonical skill package lives at: + +```text +skills/AI4Math-Lean-Agents/ +``` + +## What It Supports + +- Lean project/workspace inspection. +- Reusable `.ai4math/lean-workspace` setup for standalone Lean files. +- Theorem formalization, proof repair, proof completion, and `sorry` completion. +- Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. +- Minimal failing Lean fragment extraction when a proof is blocked. + +This project does not deploy or call Numina. Numina is referenced only as workflow provenance in the skill documentation. + +## Repository Layout + +```text +. +├── AGENTS.md +├── CLAUDE.md +├── GEMINI.md +├── README.md +├── LICENSE +├── .codex/ +├── .cursor/ +├── .github/ +├── .opencode/ +└── skills/ + └── AI4Math-Lean-Agents/ + ├── SKILL.md + ├── agents/ + ├── config/ + ├── prompts/ + ├── references/ + ├── schemas/ + ├── scripts/ + └── tests/ +``` + +## Use With Codex + +Install or sync the skill folder into your Codex skills directory: + +```bash +mkdir -p ~/.codex/skills +rsync -a --delete skills/AI4Math-Lean-Agents/ ~/.codex/skills/ai4math-lean-agents/ +``` + +Then ask Codex for Lean formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, or minimal failure extraction. + +## Helper Commands + +Run commands from the repository root: + +```bash +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py env --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --create-workspace +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py check --cwd . --skip-build +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +``` + +The helper CLI is not the proof engine. The coding agent remains responsible for reading Lean errors, editing proofs, and choosing proof strategy. + +## Validate + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +``` + +For a full local Lean workspace check: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +``` diff --git a/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md similarity index 100% rename from SKILL.md rename to skills/AI4Math-Lean-Agents/SKILL.md diff --git a/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml similarity index 100% rename from agents/openai.yaml rename to skills/AI4Math-Lean-Agents/agents/openai.yaml diff --git a/config/env.example b/skills/AI4Math-Lean-Agents/config/env.example similarity index 100% rename from config/env.example rename to skills/AI4Math-Lean-Agents/config/env.example diff --git a/config/lean_agent.example.toml b/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml similarity index 100% rename from config/lean_agent.example.toml rename to skills/AI4Math-Lean-Agents/config/lean_agent.example.toml diff --git a/prompts/complete_sorries.md b/skills/AI4Math-Lean-Agents/prompts/complete_sorries.md similarity index 100% rename from prompts/complete_sorries.md rename to skills/AI4Math-Lean-Agents/prompts/complete_sorries.md diff --git a/prompts/formalize_statement.md b/skills/AI4Math-Lean-Agents/prompts/formalize_statement.md similarity index 100% rename from prompts/formalize_statement.md rename to skills/AI4Math-Lean-Agents/prompts/formalize_statement.md diff --git a/prompts/prove_theorem.md b/skills/AI4Math-Lean-Agents/prompts/prove_theorem.md similarity index 100% rename from prompts/prove_theorem.md rename to skills/AI4Math-Lean-Agents/prompts/prove_theorem.md diff --git a/prompts/repair_lean_file.md b/skills/AI4Math-Lean-Agents/prompts/repair_lean_file.md similarity index 100% rename from prompts/repair_lean_file.md rename to skills/AI4Math-Lean-Agents/prompts/repair_lean_file.md diff --git a/references/direct_lean_workflow.md b/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md similarity index 100% rename from references/direct_lean_workflow.md rename to skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md diff --git a/references/failure_taxonomy.md b/skills/AI4Math-Lean-Agents/references/failure_taxonomy.md similarity index 100% rename from references/failure_taxonomy.md rename to skills/AI4Math-Lean-Agents/references/failure_taxonomy.md diff --git a/references/interactive_orchestration.md b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md similarity index 100% rename from references/interactive_orchestration.md rename to skills/AI4Math-Lean-Agents/references/interactive_orchestration.md diff --git a/references/lean_runtime_configuration.md b/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md similarity index 100% rename from references/lean_runtime_configuration.md rename to skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md diff --git a/references/numina_reverse_analysis.md b/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md similarity index 100% rename from references/numina_reverse_analysis.md rename to skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md diff --git a/references/review_checklist.md b/skills/AI4Math-Lean-Agents/references/review_checklist.md similarity index 100% rename from references/review_checklist.md rename to skills/AI4Math-Lean-Agents/references/review_checklist.md diff --git a/schemas/config.schema.json b/skills/AI4Math-Lean-Agents/schemas/config.schema.json similarity index 100% rename from schemas/config.schema.json rename to skills/AI4Math-Lean-Agents/schemas/config.schema.json diff --git a/schemas/result.schema.json b/skills/AI4Math-Lean-Agents/schemas/result.schema.json similarity index 100% rename from schemas/result.schema.json rename to skills/AI4Math-Lean-Agents/schemas/result.schema.json diff --git a/schemas/task.schema.json b/skills/AI4Math-Lean-Agents/schemas/task.schema.json similarity index 100% rename from schemas/task.schema.json rename to skills/AI4Math-Lean-Agents/schemas/task.schema.json diff --git a/scripts/ai4m_lean.py b/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py similarity index 100% rename from scripts/ai4m_lean.py rename to skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py diff --git a/scripts/check_lean_project.py b/skills/AI4Math-Lean-Agents/scripts/check_lean_project.py similarity index 100% rename from scripts/check_lean_project.py rename to skills/AI4Math-Lean-Agents/scripts/check_lean_project.py diff --git a/scripts/common.py b/skills/AI4Math-Lean-Agents/scripts/common.py similarity index 100% rename from scripts/common.py rename to skills/AI4Math-Lean-Agents/scripts/common.py diff --git a/scripts/configure_lean.py b/skills/AI4Math-Lean-Agents/scripts/configure_lean.py similarity index 100% rename from scripts/configure_lean.py rename to skills/AI4Math-Lean-Agents/scripts/configure_lean.py diff --git a/scripts/detect_sorry.py b/skills/AI4Math-Lean-Agents/scripts/detect_sorry.py similarity index 100% rename from scripts/detect_sorry.py rename to skills/AI4Math-Lean-Agents/scripts/detect_sorry.py diff --git a/scripts/direct_task.py b/skills/AI4Math-Lean-Agents/scripts/direct_task.py similarity index 100% rename from scripts/direct_task.py rename to skills/AI4Math-Lean-Agents/scripts/direct_task.py diff --git a/scripts/extract_minimal_failure.py b/skills/AI4Math-Lean-Agents/scripts/extract_minimal_failure.py similarity index 100% rename from scripts/extract_minimal_failure.py rename to skills/AI4Math-Lean-Agents/scripts/extract_minimal_failure.py diff --git a/scripts/tool_status.py b/skills/AI4Math-Lean-Agents/scripts/tool_status.py similarity index 100% rename from scripts/tool_status.py rename to skills/AI4Math-Lean-Agents/scripts/tool_status.py diff --git a/scripts/validate_patch.py b/skills/AI4Math-Lean-Agents/scripts/validate_patch.py similarity index 100% rename from scripts/validate_patch.py rename to skills/AI4Math-Lean-Agents/scripts/validate_patch.py diff --git a/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py similarity index 100% rename from scripts/verify_delivery.py rename to skills/AI4Math-Lean-Agents/scripts/verify_delivery.py diff --git a/tests/fixtures/after_bad.lean b/skills/AI4Math-Lean-Agents/tests/fixtures/after_bad.lean similarity index 100% rename from tests/fixtures/after_bad.lean rename to skills/AI4Math-Lean-Agents/tests/fixtures/after_bad.lean diff --git a/tests/fixtures/after_statement_changed.lean b/skills/AI4Math-Lean-Agents/tests/fixtures/after_statement_changed.lean similarity index 100% rename from tests/fixtures/after_statement_changed.lean rename to skills/AI4Math-Lean-Agents/tests/fixtures/after_statement_changed.lean diff --git a/tests/fixtures/before.lean b/skills/AI4Math-Lean-Agents/tests/fixtures/before.lean similarity index 100% rename from tests/fixtures/before.lean rename to skills/AI4Math-Lean-Agents/tests/fixtures/before.lean diff --git a/tests/fixtures/failure.lean b/skills/AI4Math-Lean-Agents/tests/fixtures/failure.lean similarity index 100% rename from tests/fixtures/failure.lean rename to skills/AI4Math-Lean-Agents/tests/fixtures/failure.lean diff --git a/tests/test_check_lean_project.py b/skills/AI4Math-Lean-Agents/tests/test_check_lean_project.py similarity index 100% rename from tests/test_check_lean_project.py rename to skills/AI4Math-Lean-Agents/tests/test_check_lean_project.py diff --git a/tests/test_cli.py b/skills/AI4Math-Lean-Agents/tests/test_cli.py similarity index 100% rename from tests/test_cli.py rename to skills/AI4Math-Lean-Agents/tests/test_cli.py diff --git a/tests/test_common_config.py b/skills/AI4Math-Lean-Agents/tests/test_common_config.py similarity index 100% rename from tests/test_common_config.py rename to skills/AI4Math-Lean-Agents/tests/test_common_config.py diff --git a/tests/test_configure_lean.py b/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py similarity index 100% rename from tests/test_configure_lean.py rename to skills/AI4Math-Lean-Agents/tests/test_configure_lean.py diff --git a/tests/test_detect_sorry.py b/skills/AI4Math-Lean-Agents/tests/test_detect_sorry.py similarity index 100% rename from tests/test_detect_sorry.py rename to skills/AI4Math-Lean-Agents/tests/test_detect_sorry.py diff --git a/tests/test_direct_task.py b/skills/AI4Math-Lean-Agents/tests/test_direct_task.py similarity index 100% rename from tests/test_direct_task.py rename to skills/AI4Math-Lean-Agents/tests/test_direct_task.py diff --git a/tests/test_validate_patch.py b/skills/AI4Math-Lean-Agents/tests/test_validate_patch.py similarity index 100% rename from tests/test_validate_patch.py rename to skills/AI4Math-Lean-Agents/tests/test_validate_patch.py From 32a2f9056958821d4f6b4a32d085b20d385d787a Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 20:31:55 +0800 Subject: [PATCH 03/37] Add Numina runtime skill design --- ...-05-24-numina-lean-agent-runtime-design.md | 254 ++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md diff --git a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md new file mode 100644 index 0000000..a2bb04e --- /dev/null +++ b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md @@ -0,0 +1,254 @@ +# Numina Lean Agent Runtime Skill Design + +## Context + +The current `ai4math-lean-agents` skill is intentionally a distilled, direct Lean coding-agent workflow. It uses the public Numina workflow as design provenance, but it does not deploy Numina, require Claude Code, call model APIs, or treat Numina as a proof backend. + +The new work adds a separate sister skill for users who explicitly want the opposite mode: fetch the official upstream Numina Lean Agent, configure a local runtime environment, and invoke the upstream runner. + +## Goal + +Create a new skill named `numina-lean-agent-runtime` that guides Codex through local deployment and invocation of the official `project-numina/numina-lean-agent` repository. + +The skill must: + +- clone or update the official upstream repository locally; +- configure required local tools and Python dependencies; +- run the upstream setup flow for a named Lean project; +- diagnose missing tools, project layout problems, and API-key gaps before long runs; +- invoke upstream `scripts.run_claude` commands for `run`, `batch`, and `from-folder` tasks; +- keep this runtime workflow separate from `ai4math-lean-agents`. + +## Non-Goals + +- Do not vendor, fork, or modify Numina source code by default. +- Do not make `ai4math-lean-agents` depend on Numina. +- Do not claim offline or key-free operation. +- Do not hide that upstream Numina may call Claude, external services, or third-party CLI skills. +- Do not store secrets in tracked files. + +## Proposed Repository Layout + +```text +skills/ + AI4Math-Lean-Agents/ + Numina-Lean-Agent-Runtime/ + SKILL.md + agents/ + openai.yaml + config/ + numina_runtime.example.toml + references/ + upstream_usage.md + scripts/ + numina_runtime.py + tests/ + test_numina_runtime.py +``` + +Use `Numina-Lean-Agent-Runtime/` as the package folder name to match the existing repository style. Use `numina-lean-agent-runtime` as the skill name in frontmatter and docs. + +## Runtime State + +Runtime state lives under `.ai4math/numina-runtime/` by default and must be ignored by git. + +```text +.ai4math/ + numina-runtime/ + upstream/ # cloned official project-numina/numina-lean-agent + projects/ # optional project workspace root used by setup.sh + results/ # default wrapper result root + .env.local # optional local environment overrides, not tracked + numina_runtime.local.toml +``` + +The wrapper must respect these environment variables: + +- `AI4MATH_NUMINA_HOME`: override runtime root. +- `NUMINA_LEAN_AGENT_REPO`: override upstream URL only when the user explicitly requests it. +- `NUMINA_LEAN_AGENT_REF`: optional branch, tag, or commit to check out. + +The default upstream URL is `https://github.com/project-numina/numina-lean-agent`. + +## CLI Wrapper + +`scripts/numina_runtime.py` provides a deterministic wrapper around upstream setup and runner commands. + +### `doctor` + +Report JSON with: + +- tool availability: `git`, `curl`, `uv`, `elan`, `lean`, `lake`, `claude`, `python`; +- upstream clone status and current commit; +- Python environment status; +- required and optional API key presence, redacted; +- whether a target path is inside a Lake project when a target is supplied. + +`doctor` must not call external model APIs. + +Credential diagnostics must distinguish: + +- Claude configuration: `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`, or an already authenticated `claude` CLI; +- Numina skill keys: `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, and `AXLE_API_KEY`; +- optional keys from required keys, because upstream Numina only needs some keys for specific backends or tools. + +### `install` + +Clone or update upstream Numina into `.ai4math/numina-runtime/upstream`. + +Default behavior: + +- clone when missing; +- fetch when present; +- checkout `NUMINA_LEAN_AGENT_REF` only when configured; +- avoid overwriting local upstream modifications without reporting them. + +The first version must include `--dry-run`, returning the clone/fetch/checkout commands without running them. + +### `configure` + +Run upstream setup for a named Lean project: + +```bash +python scripts/numina_runtime.py configure --project-name myproofs +``` + +The wrapper should: + +- ensure upstream is installed; +- run `tutorial/setup.sh ` from the upstream `tutorial/` directory; +- run `uv python install` and `uv sync` from the upstream root when `uv` is available; +- record paths and status in local JSON/TOML metadata; +- return clear next steps when `claude`, API keys, Lean, or Lake setup is missing. + +`configure` runs dependency sync by default and supports `--skip-sync` for users who only want the upstream project scaffold step. + +### `run` + +Invoke upstream single-target mode: + +```bash +python scripts/numina_runtime.py run \ + --target /path/to/Foo.lean \ + --prompt-file /path/to/prompt.md \ + --max-rounds 10 +``` + +Before launching upstream Numina, validate: + +- the target exists; +- the target is inside a Lake project with `lean-toolchain` and `lakefile.lean` or `lakefile.toml`; +- a prompt or prompt file is available; +- upstream installation and Python environment are present. + +The actual upstream command should be equivalent to: + +```bash +python -m scripts.run_claude run --prompt-file --max-rounds --result-dir +``` + +### `from-folder` + +Invoke upstream folder scanning mode: + +```bash +python scripts/numina_runtime.py from-folder \ + --target /path/to/LeanFolder \ + --prompt-file prompts/autosearch/main_entry.md \ + --max-rounds 10 +``` + +The wrapper should provide a default result directory under `.ai4math/numina-runtime/results/` if the user does not supply one. + +### `batch` + +Pass through to upstream batch mode for YAML or JSON configs: + +```bash +python scripts/numina_runtime.py batch --config /path/to/config.yaml +``` + +The wrapper should validate the config file exists and then invoke upstream `python -m scripts.run_claude batch`. + +## Skill Behavior + +The skill body should guide Codex to: + +1. Confirm the user wants official Numina runtime mode, not the distilled direct Lean workflow. +2. Run `doctor` before installation or invocation. +3. Use `install` to fetch upstream. +4. Use `configure` for first-time setup. +5. Validate the target Lake project before `run`, `batch`, or `from-folder`. +6. Report missing credentials without printing secret values. +7. Treat upstream runner output and result directories as the source of truth. +8. Fall back to `ai4math-lean-agents` only when the user chooses direct local Lean repair instead of official Numina runtime. + +## Error Handling + +The wrapper should return machine-readable JSON for all commands. + +Common statuses: + +- `ready`: local runtime is usable. +- `missing_tool`: required executable is unavailable. +- `missing_upstream`: upstream repo has not been cloned. +- `upstream_dirty`: upstream checkout has local modifications. +- `missing_credentials`: model or skill API keys are absent. +- `missing_lake_project`: target is not inside a Lake project. +- `setup_failed`: upstream setup or dependency sync failed. +- `run_failed`: upstream runner exited nonzero. + +Human-facing diagnostics should explain the next concrete command. + +## Secrets and Local Files + +Tracked files may include only examples such as: + +```text +config/numina_runtime.example.toml +``` + +Local files must be ignored: + +```text +.ai4math/numina-runtime/ +``` + +The wrapper must read `.ai4math/numina-runtime/.env.local` when present, redact values in output, and never write user-provided secrets unless the user explicitly asks. + +## Tests + +Default tests must be offline and deterministic. + +Required unit coverage: + +- Lake project root detection. +- command construction for `install`, `configure`, `run`, `from-folder`, and `batch`; +- missing tool diagnostics; +- missing upstream diagnostics; +- dirty upstream protection; +- key redaction; +- default path resolution under `.ai4math/numina-runtime`; +- JSON output shape. + +Do not clone upstream, run `uv sync`, call `claude`, or call external APIs in default tests. + +Optional integration tests may be gated by an environment variable such as `AI4MATH_NUMINA_INTEGRATION=1`. + +## Validation + +The implementation is acceptable when: + +- the new skill passes skill validation; +- repository unit tests pass; +- wrapper offline tests pass without network or API keys; +- `doctor` works on a fresh checkout and reports missing runtime state cleanly; +- `install --dry-run` or equivalent command construction test proves the official upstream URL is used; +- existing `ai4math-lean-agents` delivery verification still passes. + +## Implementation Decisions + +- `install --dry-run` is required in the first version. +- `.env.local` loading belongs in the wrapper, with redacted reporting. +- `configure` runs `uv sync` by default and supports `--skip-sync`. +- Validation remains per skill; do not add a repository-level `verify-all` helper in the first version. From e58e13d3d4abb3ebda40387a6ac4084da057cba2 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 20:41:07 +0800 Subject: [PATCH 04/37] Translate Numina runtime design spec --- ...-05-24-numina-lean-agent-runtime-design.md | 244 +++++++++--------- 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md index a2bb04e..88e2f4d 100644 --- a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md +++ b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md @@ -1,33 +1,33 @@ -# Numina Lean Agent Runtime Skill Design +# Numina Lean Agent Runtime Skill 设计 -## Context +## 背景 -The current `ai4math-lean-agents` skill is intentionally a distilled, direct Lean coding-agent workflow. It uses the public Numina workflow as design provenance, but it does not deploy Numina, require Claude Code, call model APIs, or treat Numina as a proof backend. +当前的 `ai4math-lean-agents` skill 是一个有意保持轻量的“蒸馏版”直接 Lean coding-agent 工作流。它把公开 Numina 工作流当作设计来源,但不部署 Numina、不要求 Claude Code、不调用模型 API,也不把 Numina 当成证明后端。 -The new work adds a separate sister skill for users who explicitly want the opposite mode: fetch the official upstream Numina Lean Agent, configure a local runtime environment, and invoke the upstream runner. +新的工作要补上另一种模式:当用户明确想调用原版 Numina 时,创建一个独立的 sister skill,负责抓取官方上游 Numina Lean Agent、配置本地运行环境,并调用上游 runner。 -## Goal +## 目标 -Create a new skill named `numina-lean-agent-runtime` that guides Codex through local deployment and invocation of the official `project-numina/numina-lean-agent` repository. +创建新 skill:`numina-lean-agent-runtime`。它指导 Codex 在本地部署并调用官方 `project-numina/numina-lean-agent` 仓库。 -The skill must: +这个 skill 必须支持: -- clone or update the official upstream repository locally; -- configure required local tools and Python dependencies; -- run the upstream setup flow for a named Lean project; -- diagnose missing tools, project layout problems, and API-key gaps before long runs; -- invoke upstream `scripts.run_claude` commands for `run`, `batch`, and `from-folder` tasks; -- keep this runtime workflow separate from `ai4math-lean-agents`. +- 在本地 clone 或更新官方上游仓库; +- 配置所需本地工具和 Python 依赖; +- 为指定 Lean 项目运行上游 setup 流程; +- 在长时间运行前诊断缺失工具、Lean 项目布局问题和 API key 缺口; +- 调用上游 `scripts.run_claude` 的 `run`、`batch` 和 `from-folder` 任务; +- 保持这个 runtime 工作流和 `ai4math-lean-agents` 相互独立。 -## Non-Goals +## 非目标 -- Do not vendor, fork, or modify Numina source code by default. -- Do not make `ai4math-lean-agents` depend on Numina. -- Do not claim offline or key-free operation. -- Do not hide that upstream Numina may call Claude, external services, or third-party CLI skills. -- Do not store secrets in tracked files. +- 默认不 vendor、不 fork、不修改 Numina 源码。 +- 不让 `ai4math-lean-agents` 依赖 Numina。 +- 不声称离线可用,也不声称无需 key。 +- 不隐藏上游 Numina 可能调用 Claude、外部服务或第三方 CLI skills。 +- 不把密钥写入被 git 跟踪的文件。 -## Proposed Repository Layout +## 仓库布局 ```text skills/ @@ -46,86 +46,86 @@ skills/ test_numina_runtime.py ``` -Use `Numina-Lean-Agent-Runtime/` as the package folder name to match the existing repository style. Use `numina-lean-agent-runtime` as the skill name in frontmatter and docs. +目录名使用 `Numina-Lean-Agent-Runtime/`,保持和当前仓库的技能包风格一致。skill frontmatter 和文档中的 skill 名使用 `numina-lean-agent-runtime`。 -## Runtime State +## 运行状态目录 -Runtime state lives under `.ai4math/numina-runtime/` by default and must be ignored by git. +默认运行状态放在 `.ai4math/numina-runtime/`,并且必须被 git 忽略。 ```text .ai4math/ numina-runtime/ - upstream/ # cloned official project-numina/numina-lean-agent - projects/ # optional project workspace root used by setup.sh - results/ # default wrapper result root - .env.local # optional local environment overrides, not tracked + upstream/ # clone 下来的官方 project-numina/numina-lean-agent + projects/ # setup.sh 使用的可选项目工作区根目录 + results/ # wrapper 默认结果目录 + .env.local # 可选本地环境变量覆盖,不跟踪 numina_runtime.local.toml ``` -The wrapper must respect these environment variables: +wrapper 必须支持这些环境变量: -- `AI4MATH_NUMINA_HOME`: override runtime root. -- `NUMINA_LEAN_AGENT_REPO`: override upstream URL only when the user explicitly requests it. -- `NUMINA_LEAN_AGENT_REF`: optional branch, tag, or commit to check out. +- `AI4MATH_NUMINA_HOME`:覆盖 runtime 根目录。 +- `NUMINA_LEAN_AGENT_REPO`:仅在用户明确要求时覆盖上游仓库 URL。 +- `NUMINA_LEAN_AGENT_REF`:可选 branch、tag 或 commit。 -The default upstream URL is `https://github.com/project-numina/numina-lean-agent`. +默认上游 URL 是 `https://github.com/project-numina/numina-lean-agent`。 ## CLI Wrapper -`scripts/numina_runtime.py` provides a deterministic wrapper around upstream setup and runner commands. +`scripts/numina_runtime.py` 提供一层确定性 wrapper,负责包装上游 setup 和 runner 命令。 ### `doctor` -Report JSON with: +输出 JSON 报告: -- tool availability: `git`, `curl`, `uv`, `elan`, `lean`, `lake`, `claude`, `python`; -- upstream clone status and current commit; -- Python environment status; -- required and optional API key presence, redacted; -- whether a target path is inside a Lake project when a target is supplied. +- 工具可用性:`git`、`curl`、`uv`、`elan`、`lean`、`lake`、`claude`、`python`; +- 上游 clone 状态和当前 commit; +- Python 环境状态; +- required/optional API key 是否存在,输出时必须 redacted; +- 如果传入 target,检查它是否位于 Lake 项目内。 -`doctor` must not call external model APIs. +`doctor` 不得调用外部模型 API。 -Credential diagnostics must distinguish: +credential 诊断必须区分: -- Claude configuration: `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`, or an already authenticated `claude` CLI; -- Numina skill keys: `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, and `AXLE_API_KEY`; -- optional keys from required keys, because upstream Numina only needs some keys for specific backends or tools. +- Claude 配置:`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_BASE_URL`、`ANTHROPIC_MODEL`,或已经登录可用的 `claude` CLI; +- Numina skill keys:`GEMINI_API_KEY`、`OPENAI_API_KEY`、`LEAN_LEANDEX_API_KEY`、`AXLE_API_KEY`; +- required keys 和 optional keys,因为上游 Numina 只在特定 backend 或工具路径下需要部分 key。 ### `install` -Clone or update upstream Numina into `.ai4math/numina-runtime/upstream`. +把上游 Numina clone 或更新到 `.ai4math/numina-runtime/upstream`。 -Default behavior: +默认行为: -- clone when missing; -- fetch when present; -- checkout `NUMINA_LEAN_AGENT_REF` only when configured; -- avoid overwriting local upstream modifications without reporting them. +- 缺失时 clone; +- 已存在时 fetch; +- 仅在配置 `NUMINA_LEAN_AGENT_REF` 时 checkout 指定 ref; +- 如果上游 checkout 有本地修改,不覆盖,必须报告。 -The first version must include `--dry-run`, returning the clone/fetch/checkout commands without running them. +第一版必须支持 `--dry-run`,返回 clone/fetch/checkout 命令,但不实际执行。 ### `configure` -Run upstream setup for a named Lean project: +为指定 Lean 项目运行上游 setup: ```bash python scripts/numina_runtime.py configure --project-name myproofs ``` -The wrapper should: +wrapper 需要: -- ensure upstream is installed; -- run `tutorial/setup.sh ` from the upstream `tutorial/` directory; -- run `uv python install` and `uv sync` from the upstream root when `uv` is available; -- record paths and status in local JSON/TOML metadata; -- return clear next steps when `claude`, API keys, Lean, or Lake setup is missing. +- 确保上游仓库已安装; +- 从上游 `tutorial/` 目录运行 `tutorial/setup.sh `; +- 当 `uv` 可用时,在上游根目录运行 `uv python install` 和 `uv sync`; +- 把路径和状态记录到本地 JSON/TOML metadata; +- 当 `claude`、API keys、Lean 或 Lake 配置缺失时,返回明确下一步。 -`configure` runs dependency sync by default and supports `--skip-sync` for users who only want the upstream project scaffold step. +`configure` 默认执行依赖同步,并支持 `--skip-sync`,给只想生成上游项目脚手架的用户使用。 ### `run` -Invoke upstream single-target mode: +调用上游单目标模式: ```bash python scripts/numina_runtime.py run \ @@ -134,14 +134,14 @@ python scripts/numina_runtime.py run \ --max-rounds 10 ``` -Before launching upstream Numina, validate: +启动上游 Numina 前先验证: -- the target exists; -- the target is inside a Lake project with `lean-toolchain` and `lakefile.lean` or `lakefile.toml`; -- a prompt or prompt file is available; -- upstream installation and Python environment are present. +- target 存在; +- target 位于包含 `lean-toolchain` 和 `lakefile.lean` 或 `lakefile.toml` 的 Lake 项目内; +- 已提供 prompt 或 prompt file; +- 上游安装和 Python 环境已存在。 -The actual upstream command should be equivalent to: +实际上游命令应等价于: ```bash python -m scripts.run_claude run --prompt-file --max-rounds --result-dir @@ -149,7 +149,7 @@ python -m scripts.run_claude run --prompt-file --max-roun ### `from-folder` -Invoke upstream folder scanning mode: +调用上游文件夹扫描模式: ```bash python scripts/numina_runtime.py from-folder \ @@ -158,97 +158,97 @@ python scripts/numina_runtime.py from-folder \ --max-rounds 10 ``` -The wrapper should provide a default result directory under `.ai4math/numina-runtime/results/` if the user does not supply one. +如果用户没有提供结果目录,wrapper 应默认使用 `.ai4math/numina-runtime/results/` 下的目录。 ### `batch` -Pass through to upstream batch mode for YAML or JSON configs: +透传到上游 YAML 或 JSON config 的 batch 模式: ```bash python scripts/numina_runtime.py batch --config /path/to/config.yaml ``` -The wrapper should validate the config file exists and then invoke upstream `python -m scripts.run_claude batch`. +wrapper 必须先验证 config 文件存在,然后调用上游 `python -m scripts.run_claude batch`。 -## Skill Behavior +## Skill 行为 -The skill body should guide Codex to: +skill body 应指导 Codex: -1. Confirm the user wants official Numina runtime mode, not the distilled direct Lean workflow. -2. Run `doctor` before installation or invocation. -3. Use `install` to fetch upstream. -4. Use `configure` for first-time setup. -5. Validate the target Lake project before `run`, `batch`, or `from-folder`. -6. Report missing credentials without printing secret values. -7. Treat upstream runner output and result directories as the source of truth. -8. Fall back to `ai4math-lean-agents` only when the user chooses direct local Lean repair instead of official Numina runtime. +1. 先确认用户想要官方 Numina runtime 模式,而不是蒸馏版 direct Lean 工作流。 +2. 在安装或调用前先运行 `doctor`。 +3. 用 `install` 抓取上游。 +4. 第一次设置时用 `configure`。 +5. 在 `run`、`batch` 或 `from-folder` 前验证目标 Lake 项目。 +6. 报告缺失 credential,但不打印 secret value。 +7. 把上游 runner 输出和 result directories 当作事实来源。 +8. 只有当用户选择直接本地 Lean repair 时,才回退到 `ai4math-lean-agents`。 -## Error Handling +## 错误处理 -The wrapper should return machine-readable JSON for all commands. +wrapper 的所有命令都应返回 machine-readable JSON。 -Common statuses: +常见 status: -- `ready`: local runtime is usable. -- `missing_tool`: required executable is unavailable. -- `missing_upstream`: upstream repo has not been cloned. -- `upstream_dirty`: upstream checkout has local modifications. -- `missing_credentials`: model or skill API keys are absent. -- `missing_lake_project`: target is not inside a Lake project. -- `setup_failed`: upstream setup or dependency sync failed. -- `run_failed`: upstream runner exited nonzero. +- `ready`:本地 runtime 可用。 +- `missing_tool`:缺少必需可执行文件。 +- `missing_upstream`:上游仓库尚未 clone。 +- `upstream_dirty`:上游 checkout 有本地修改。 +- `missing_credentials`:缺少模型或 skill API keys。 +- `missing_lake_project`:target 不在 Lake 项目内。 +- `setup_failed`:上游 setup 或 dependency sync 失败。 +- `run_failed`:上游 runner 非零退出。 -Human-facing diagnostics should explain the next concrete command. +面向人的 diagnostics 应说明下一条具体命令。 -## Secrets and Local Files +## Secrets 和本地文件 -Tracked files may include only examples such as: +被 git 跟踪的文件只能包含 example,例如: ```text config/numina_runtime.example.toml ``` -Local files must be ignored: +本地文件必须被忽略: ```text .ai4math/numina-runtime/ ``` -The wrapper must read `.ai4math/numina-runtime/.env.local` when present, redact values in output, and never write user-provided secrets unless the user explicitly asks. +wrapper 必须在存在时读取 `.ai4math/numina-runtime/.env.local`,输出时 redacted,并且除非用户明确要求,不写入用户密钥。 -## Tests +## 测试 -Default tests must be offline and deterministic. +默认测试必须离线且确定性。 -Required unit coverage: +必需单测覆盖: -- Lake project root detection. -- command construction for `install`, `configure`, `run`, `from-folder`, and `batch`; -- missing tool diagnostics; -- missing upstream diagnostics; -- dirty upstream protection; -- key redaction; -- default path resolution under `.ai4math/numina-runtime`; -- JSON output shape. +- Lake project root detection; +- `install`、`configure`、`run`、`from-folder` 和 `batch` 的命令构造; +- missing tool diagnostics; +- missing upstream diagnostics; +- dirty upstream protection; +- key redaction; +- `.ai4math/numina-runtime` 下默认路径解析; +- JSON output shape。 -Do not clone upstream, run `uv sync`, call `claude`, or call external APIs in default tests. +默认测试不得 clone 上游、运行 `uv sync`、调用 `claude` 或调用外部 API。 -Optional integration tests may be gated by an environment variable such as `AI4MATH_NUMINA_INTEGRATION=1`. +可选集成测试可以用环境变量门控,例如 `AI4MATH_NUMINA_INTEGRATION=1`。 -## Validation +## 验证 -The implementation is acceptable when: +实现可接受的条件: -- the new skill passes skill validation; -- repository unit tests pass; -- wrapper offline tests pass without network or API keys; -- `doctor` works on a fresh checkout and reports missing runtime state cleanly; -- `install --dry-run` or equivalent command construction test proves the official upstream URL is used; -- existing `ai4math-lean-agents` delivery verification still passes. +- 新 skill 通过 skill validation; +- 仓库单测通过; +- wrapper 离线测试在无网络、无 API keys 情况下通过; +- `doctor` 在 fresh checkout 上能正常运行,并清楚报告缺失 runtime state; +- `install --dry-run` 或等价命令构造测试证明使用官方上游 URL; +- 现有 `ai4math-lean-agents` delivery verification 仍然通过。 -## Implementation Decisions +## 实现决策 -- `install --dry-run` is required in the first version. -- `.env.local` loading belongs in the wrapper, with redacted reporting. -- `configure` runs `uv sync` by default and supports `--skip-sync`. -- Validation remains per skill; do not add a repository-level `verify-all` helper in the first version. +- 第一版必须支持 `install --dry-run`。 +- `.env.local` 读取放在 wrapper 中,输出 redacted 状态。 +- `configure` 默认运行 `uv sync`,并支持 `--skip-sync`。 +- 第一版保持 per-skill 验证,不新增仓库级 `verify-all` helper。 From 3fc5248a71d9fd7f9d3713c893c6958f882cd08a Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 21:08:27 +0800 Subject: [PATCH 05/37] Revise Numina design for existing skill --- ...-05-24-numina-lean-agent-runtime-design.md | 377 +++++++++++------- 1 file changed, 241 insertions(+), 136 deletions(-) diff --git a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md index 88e2f4d..d04f84f 100644 --- a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md +++ b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md @@ -1,254 +1,359 @@ -# Numina Lean Agent Runtime Skill 设计 +# AI4Math Lean Agents 调用原版 Numina 改造设计 ## 背景 -当前的 `ai4math-lean-agents` skill 是一个有意保持轻量的“蒸馏版”直接 Lean coding-agent 工作流。它把公开 Numina 工作流当作设计来源,但不部署 Numina、不要求 Claude Code、不调用模型 API,也不把 Numina 当成证明后端。 +当前 `AI4Math-Lean-Agents` skill 的定位是“蒸馏版”直接 Lean coding-agent 工作流:Codex 自己读写 Lean,CLI 只做确定性 guardrail,并且文档明确写着不部署、不调用 Numina。 -新的工作要补上另一种模式:当用户明确想调用原版 Numina 时,创建一个独立的 sister skill,负责抓取官方上游 Numina Lean Agent、配置本地运行环境,并调用上游 runner。 +用户现在希望保留这个 skill 的总框架,但把定位改成:**自动抓取官方原版 Numina Lean Agent,在本地交互配置环境,然后调用上游 Numina runner**。直接 Lean 操作仍可作为诊断、review、最小失败 handoff 和 fallback,但不再是唯一主路径。 ## 目标 -创建新 skill:`numina-lean-agent-runtime`。它指导 Codex 在本地部署并调用官方 `project-numina/numina-lean-agent` 仓库。 +改造现有 `skills/AI4Math-Lean-Agents/`,不新增 sister skill。 -这个 skill 必须支持: +改造后,这个 skill 必须支持: -- 在本地 clone 或更新官方上游仓库; -- 配置所需本地工具和 Python 依赖; -- 为指定 Lean 项目运行上游 setup 流程; -- 在长时间运行前诊断缺失工具、Lean 项目布局问题和 API key 缺口; -- 调用上游 `scripts.run_claude` 的 `run`、`batch` 和 `from-folder` 任务; -- 保持这个 runtime 工作流和 `ai4math-lean-agents` 相互独立。 +- clone 或更新官方 `project-numina/numina-lean-agent`; +- 本地配置 Numina 运行环境、Python 依赖、Claude CLI/API key 和相关 skill keys; +- 为用户的 Lean/Lake 项目调用官方 Numina runner; +- 在调用前检查工具、credential、Lake 项目结构和上游 checkout 状态; +- 保留现有 Lean/Lake 校验、patch review、`sorry` 检测、最小失败提取等 guardrails; +- 明确告诉用户:默认证明/修复路线会调用原版 Numina,可能产生外部 API 调用和费用。 ## 非目标 +- 不创建新的 `Numina-Lean-Agent-Runtime/` skill 目录。 - 默认不 vendor、不 fork、不修改 Numina 源码。 -- 不让 `ai4math-lean-agents` 依赖 Numina。 -- 不声称离线可用,也不声称无需 key。 -- 不隐藏上游 Numina 可能调用 Claude、外部服务或第三方 CLI skills。 -- 不把密钥写入被 git 跟踪的文件。 +- 不把密钥写入 git 跟踪文件。 +- 不假装离线、无 key、无外部 API 可完成 Numina 路线。 +- 不删除现有直接 Lean 工具;它们继续服务于检查、review、fallback 和失败最小化。 -## 仓库布局 +## 保持不大动的现有框架 + +继续使用现有包: ```text skills/ AI4Math-Lean-Agents/ - Numina-Lean-Agent-Runtime/ SKILL.md agents/ openai.yaml config/ - numina_runtime.example.toml + prompts/ references/ - upstream_usage.md + schemas/ scripts/ - numina_runtime.py tests/ - test_numina_runtime.py ``` -目录名使用 `Numina-Lean-Agent-Runtime/`,保持和当前仓库的技能包风格一致。skill frontmatter 和文档中的 skill 名使用 `numina-lean-agent-runtime`。 +在现有框架内新增: + +```text +skills/AI4Math-Lean-Agents/ + config/ + numina_runtime.example.toml + references/ + numina_runtime.md + scripts/ + numina_runtime.py + tests/ + test_numina_runtime.py +``` + +并更新: + +```text +skills/AI4Math-Lean-Agents/ + SKILL.md + agents/openai.yaml + scripts/ai4m_lean.py + scripts/verify_delivery.py + README.md + AGENTS.md + CLAUDE.md + GEMINI.md +``` ## 运行状态目录 -默认运行状态放在 `.ai4math/numina-runtime/`,并且必须被 git 忽略。 +Numina runtime 状态默认放在 `.ai4math/numina-runtime/`,必须被 `.ai4math/.gitignore` 忽略。 ```text .ai4math/ numina-runtime/ - upstream/ # clone 下来的官方 project-numina/numina-lean-agent - projects/ # setup.sh 使用的可选项目工作区根目录 + upstream/ # 官方 project-numina/numina-lean-agent clone + projects/ # setup.sh 可用的本地项目工作区 results/ # wrapper 默认结果目录 .env.local # 可选本地环境变量覆盖,不跟踪 numina_runtime.local.toml ``` -wrapper 必须支持这些环境变量: +wrapper 必须支持: - `AI4MATH_NUMINA_HOME`:覆盖 runtime 根目录。 - `NUMINA_LEAN_AGENT_REPO`:仅在用户明确要求时覆盖上游仓库 URL。 - `NUMINA_LEAN_AGENT_REF`:可选 branch、tag 或 commit。 -默认上游 URL 是 `https://github.com/project-numina/numina-lean-agent`。 +默认上游 URL 固定为: -## CLI Wrapper +```text +https://github.com/project-numina/numina-lean-agent +``` -`scripts/numina_runtime.py` 提供一层确定性 wrapper,负责包装上游 setup 和 runner 命令。 +## CLI 设计 -### `doctor` +继续用 `scripts/ai4m_lean.py` 作为总入口,在现有命令旁新增 Numina runtime 命令。 -输出 JSON 报告: +```bash +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-doctor --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-configure --cwd . --project-name myproofs +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-run --cwd . --file /path/to/Foo.lean --prompt-file /path/to/prompt.md +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-from-folder --cwd . --folder /path/to/LeanFolder +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-batch --cwd . --config /path/to/config.yaml +``` -- 工具可用性:`git`、`curl`、`uv`、`elan`、`lean`、`lake`、`claude`、`python`; -- 上游 clone 状态和当前 commit; -- Python 环境状态; -- required/optional API key 是否存在,输出时必须 redacted; -- 如果传入 target,检查它是否位于 Lake 项目内。 +底层实现放在 `scripts/numina_runtime.py`,`ai4m_lean.py` 只负责参数解析、调用和统一 exit code。 -`doctor` 不得调用外部模型 API。 +## 现有命令语义调整 -credential 诊断必须区分: +### 保持原样的 guardrail 命令 -- Claude 配置:`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_BASE_URL`、`ANTHROPIC_MODEL`,或已经登录可用的 `claude` CLI; -- Numina skill keys:`GEMINI_API_KEY`、`OPENAI_API_KEY`、`LEAN_LEANDEX_API_KEY`、`AXLE_API_KEY`; -- required keys 和 optional keys,因为上游 Numina 只在特定 backend 或工具路径下需要部分 key。 +这些命令继续是本地确定性工具,不调用外部 API: + +- `env` +- `doctor` +- `check` +- `review` +- `detect-sorry` +- `minimize-failure` +- `verify-delivery` + +其中 `doctor` 和 `env` 应补充 Numina runtime readiness 摘要,但不得自动 clone、安装或调用模型。 -### `install` +### 扩展 `configure` -把上游 Numina clone 或更新到 `.ai4math/numina-runtime/upstream`。 +现有 `configure --create-workspace` 继续保留,用于 Lean workspace。 + +新增可选 Numina 配置路径: + +```bash +python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs +``` + +它等价于执行: + +1. `numina-install` +2. `numina-configure --project-name myproofs` + +### 改造任务命令 + +这些任务命令应默认进入 Numina runtime 路线: + +- `prove` +- `formalize` +- `repair` +- `complete-sorries` +- `batch` 默认行为: -- 缺失时 clone; -- 已存在时 fetch; -- 仅在配置 `NUMINA_LEAN_AGENT_REF` 时 checkout 指定 ref; -- 如果上游 checkout 有本地修改,不覆盖,必须报告。 +1. 检查 target 或 folder 是否存在。 +2. 检查 target 是否在 Lake 项目内。 +3. 检查 Numina runtime 是否已安装、依赖是否准备好、credential 是否足够。 +4. 如果缺 runtime,返回 `missing_numina_runtime` 和下一步命令,不静默 fallback。 +5. 如果 runtime ready,则构造并执行官方 Numina runner 命令。 -第一版必须支持 `--dry-run`,返回 clone/fetch/checkout 命令,但不实际执行。 +为保留现有轻量能力,第一版允许 `--direct` 或 `--dry-run`: -### `configure` +- `--dry-run`:只返回 Numina command plan,不执行。 +- `--direct`:沿用现有 direct coding-agent task envelope,用于用户明确要求不调用 Numina 的场景。 -为指定 Lean 项目运行上游 setup: +## Numina Runtime Wrapper -```bash -python scripts/numina_runtime.py configure --project-name myproofs -``` +`scripts/numina_runtime.py` 需要提供可单测的纯函数和命令入口。 -wrapper 需要: +### `numina-doctor` -- 确保上游仓库已安装; -- 从上游 `tutorial/` 目录运行 `tutorial/setup.sh `; -- 当 `uv` 可用时,在上游根目录运行 `uv python install` 和 `uv sync`; -- 把路径和状态记录到本地 JSON/TOML metadata; -- 当 `claude`、API keys、Lean 或 Lake 配置缺失时,返回明确下一步。 +输出 JSON,包含: -`configure` 默认执行依赖同步,并支持 `--skip-sync`,给只想生成上游项目脚手架的用户使用。 +- `git`、`curl`、`uv`、`elan`、`lean`、`lake`、`claude`、`python` 可用性; +- 上游是否已 clone、当前 commit、是否 dirty; +- Python/uv 环境状态; +- credential 状态,必须 redacted; +- 目标路径的 Lake 项目检测结果。 -### `run` +credential 诊断区分: -调用上游单目标模式: +- Claude 配置:`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_BASE_URL`、`ANTHROPIC_MODEL`,或已经可用的 `claude` CLI; +- Numina skill keys:`GEMINI_API_KEY`、`OPENAI_API_KEY`、`LEAN_LEANDEX_API_KEY`、`AXLE_API_KEY`; +- required 和 optional keys。 + +`numina-doctor` 不得调用外部模型 API。 + +### `numina-install` + +clone 或更新官方 Numina: + +- 缺失时 clone; +- 已存在时 fetch; +- 配置 `NUMINA_LEAN_AGENT_REF` 时 checkout 指定 ref; +- 上游 checkout dirty 时不覆盖,返回 `upstream_dirty`。 + +第一版必须支持: ```bash -python scripts/numina_runtime.py run \ - --target /path/to/Foo.lean \ - --prompt-file /path/to/prompt.md \ - --max-rounds 10 +python scripts/ai4m_lean.py numina-install --cwd . --dry-run ``` -启动上游 Numina 前先验证: +`--dry-run` 返回将执行的 clone/fetch/checkout 命令,不实际执行。 -- target 存在; -- target 位于包含 `lean-toolchain` 和 `lakefile.lean` 或 `lakefile.toml` 的 Lake 项目内; -- 已提供 prompt 或 prompt file; -- 上游安装和 Python 环境已存在。 +### `numina-configure` -实际上游命令应等价于: +为指定 project name 运行上游 setup: ```bash -python -m scripts.run_claude run --prompt-file --max-rounds --result-dir +python scripts/ai4m_lean.py numina-configure --cwd . --project-name myproofs ``` -### `from-folder` +行为: + +- 确保上游已安装; +- 从上游 `tutorial/` 目录运行 `setup.sh `; +- 默认在上游根目录运行 `uv python install` 和 `uv sync`; +- 支持 `--skip-sync`; +- 记录本地 metadata; +- 失败时返回 `setup_failed` 和具体 stderr/stdout 摘要。 + +### `numina-run` -调用上游文件夹扫描模式: +单文件调用官方 runner: ```bash -python scripts/numina_runtime.py from-folder \ - --target /path/to/LeanFolder \ - --prompt-file prompts/autosearch/main_entry.md \ +python scripts/ai4m_lean.py numina-run \ + --cwd . \ + --file /path/to/Foo.lean \ + --prompt-file /path/to/prompt.md \ --max-rounds 10 ``` -如果用户没有提供结果目录,wrapper 应默认使用 `.ai4math/numina-runtime/results/` 下的目录。 +启动前必须验证: -### `batch` +- 文件存在; +- 文件在 Lake 项目内; +- prompt 或 prompt file 存在; +- 上游安装、uv 环境和 credential 状态可用。 -透传到上游 YAML 或 JSON config 的 batch 模式: +实际上游命令等价于: ```bash -python scripts/numina_runtime.py batch --config /path/to/config.yaml +python -m scripts.run_claude run --prompt-file --max-rounds --result-dir ``` -wrapper 必须先验证 config 文件存在,然后调用上游 `python -m scripts.run_claude batch`。 +### `numina-from-folder` + +文件夹模式调用: + +```bash +python scripts/ai4m_lean.py numina-from-folder --cwd . --folder /path/to/LeanFolder +``` -## Skill 行为 +默认 result dir 放在 `.ai4math/numina-runtime/results/`。 -skill body 应指导 Codex: +### `numina-batch` -1. 先确认用户想要官方 Numina runtime 模式,而不是蒸馏版 direct Lean 工作流。 -2. 在安装或调用前先运行 `doctor`。 -3. 用 `install` 抓取上游。 -4. 第一次设置时用 `configure`。 -5. 在 `run`、`batch` 或 `from-folder` 前验证目标 Lake 项目。 -6. 报告缺失 credential,但不打印 secret value。 -7. 把上游 runner 输出和 result directories 当作事实来源。 -8. 只有当用户选择直接本地 Lean repair 时,才回退到 `ai4math-lean-agents`。 +批量配置调用: -## 错误处理 +```bash +python scripts/ai4m_lean.py numina-batch --cwd . --config /path/to/config.yaml +``` -wrapper 的所有命令都应返回 machine-readable JSON。 +wrapper 先验证 config 存在,再调用上游 batch。 -常见 status: +## Skill 文档改造 -- `ready`:本地 runtime 可用。 -- `missing_tool`:缺少必需可执行文件。 -- `missing_upstream`:上游仓库尚未 clone。 -- `upstream_dirty`:上游 checkout 有本地修改。 -- `missing_credentials`:缺少模型或 skill API keys。 -- `missing_lake_project`:target 不在 Lake 项目内。 -- `setup_failed`:上游 setup 或 dependency sync 失败。 -- `run_failed`:上游 runner 非零退出。 +`SKILL.md` 需要从“Numina 不部署不调用”改成: -面向人的 diagnostics 应说明下一条具体命令。 +- 默认工作流是官方 Numina runtime assisted workflow; +- Codex 先用本地 guardrails 识别目标、检查 Lake 项目、检查 runtime; +- runtime 未安装时,引导 `numina-install` 和 `numina-configure`; +- runtime ready 时调用官方 Numina runner; +- runner 结束后用 `check`、`detect-sorry`、`review` 做交付前验证; +- 如果 Numina 路线失败,使用 `minimize-failure` 给出最小失败片段和下一步。 -## Secrets 和本地文件 +`references/numina_reverse_analysis.md` 可以保留,但应改为历史/背景材料,不再承担“只蒸馏不调用”的政策含义。 -被 git 跟踪的文件只能包含 example,例如: +## 安全和本地文件 -```text -config/numina_runtime.example.toml -``` +被 git 跟踪的文件只能包含 example config。 -本地文件必须被忽略: +本地文件必须忽略: ```text .ai4math/numina-runtime/ ``` -wrapper 必须在存在时读取 `.ai4math/numina-runtime/.env.local`,输出时 redacted,并且除非用户明确要求,不写入用户密钥。 +wrapper 必须读取 `.ai4math/numina-runtime/.env.local`(如果存在),但输出 redacted 状态,不打印真实 secret。除非用户明确要求,不写入用户密钥。 + +## 错误状态 + +新增或使用这些 status: + +- `numina_ready` +- `missing_numina_runtime` +- `missing_numina_credentials` +- `missing_lake_project` +- `upstream_dirty` +- `numina_setup_failed` +- `numina_run_failed` +- `direct_task_ready` + +`ai4m_lean.py` 需要把 Numina 相关失败映射到稳定 exit code,避免和 Lean 编译失败混淆。 ## 测试 -默认测试必须离线且确定性。 +默认测试必须离线、确定性、无 API。 + +新增单测覆盖: -必需单测覆盖: +- Numina runtime 默认路径解析; +- `.ai4math/.gitignore` 写入 `numina-runtime/`; +- Lake project root detection 复用现有逻辑; +- `numina-install --dry-run` 使用官方上游 URL; +- dirty upstream 保护; +- credential redaction; +- `numina-run`、`numina-from-folder`、`numina-batch` 命令构造; +- `prove/repair/complete-sorries/batch --dry-run` 走 Numina command plan; +- `--direct` 保留旧 direct task envelope; +- `verify-delivery` 检查新增文件和命令。 -- Lake project root detection; -- `install`、`configure`、`run`、`from-folder` 和 `batch` 的命令构造; -- missing tool diagnostics; -- missing upstream diagnostics; -- dirty upstream protection; -- key redaction; -- `.ai4math/numina-runtime` 下默认路径解析; -- JSON output shape。 +默认测试不得: -默认测试不得 clone 上游、运行 `uv sync`、调用 `claude` 或调用外部 API。 +- clone 官方仓库; +- 运行 `uv sync`; +- 调用 `claude`; +- 调用外部 API。 -可选集成测试可以用环境变量门控,例如 `AI4MATH_NUMINA_INTEGRATION=1`。 +可选集成测试用环境变量门控: + +```text +AI4MATH_NUMINA_INTEGRATION=1 +``` -## 验证 +## 验收标准 -实现可接受的条件: +实现完成时必须满足: -- 新 skill 通过 skill validation; -- 仓库单测通过; -- wrapper 离线测试在无网络、无 API keys 情况下通过; -- `doctor` 在 fresh checkout 上能正常运行,并清楚报告缺失 runtime state; -- `install --dry-run` 或等价命令构造测试证明使用官方上游 URL; -- 现有 `ai4math-lean-agents` delivery verification 仍然通过。 +- `verify-delivery --run-tests` 通过; +- 新增 Numina runtime offline tests 通过; +- `numina-install --dry-run` 输出官方上游 URL; +- `numina-doctor` 在未安装 runtime 的 fresh checkout 上清楚报告下一步; +- `SKILL.md`、README、AGENTS/CLAUDE/GEMINI 说明一致:本 skill 现在会部署并调用官方 Numina; +- 最终交付仍拒绝 `sorry`、`admit` 和新 `axiom`。 ## 实现决策 -- 第一版必须支持 `install --dry-run`。 -- `.env.local` 读取放在 wrapper 中,输出 redacted 状态。 -- `configure` 默认运行 `uv sync`,并支持 `--skip-sync`。 -- 第一版保持 per-skill 验证,不新增仓库级 `verify-all` helper。 +- 不新增 sister skill,直接改造 `AI4Math-Lean-Agents`。 +- 保留现有 direct Lean guardrails。 +- 证明/修复类任务默认准备或调用 Numina runtime。 +- 第一版必须支持 `--dry-run` 和 `--direct`,降低迁移风险。 +- 默认 runtime 根目录是 `.ai4math/numina-runtime/`。 From b90efba96c1b6c0735f9113844b0b1c1df0c7027 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 21:19:45 +0800 Subject: [PATCH 06/37] Add Numina runtime implementation plan --- .../2026-05-24-ai4math-numina-runtime.md | 1432 +++++++++++++++++ 1 file changed, 1432 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md diff --git a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md new file mode 100644 index 0000000..5137a4b --- /dev/null +++ b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md @@ -0,0 +1,1432 @@ +# AI4Math Numina Runtime Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 改造现有 `AI4Math-Lean-Agents` skill,使其能自动部署并调用官方 `project-numina/numina-lean-agent`,同时保留现有 Lean guardrails 和 direct fallback。 + +**Architecture:** 新增 `scripts/numina_runtime.py` 作为纯 Python runtime wrapper,负责本地路径、credential redaction、上游状态、dry-run install、setup 和 runner command plan。`scripts/ai4m_lean.py` 继续作为唯一 CLI 总入口,新增 `numina-*` 子命令,并让 `prove/repair/formalize/complete-sorries/batch` 默认走 Numina runtime,`--direct` 保留旧 direct task envelope。文档和 delivery verifier 更新为“官方 Numina runtime assisted workflow”。 + +**Tech Stack:** Python 3 standard library, `unittest`, existing Lean/Lake helper modules, `git`, `uv`, `claude` CLI, official `project-numina/numina-lean-agent`. + +--- + +## File Structure + +- Create `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: deterministic Numina runtime wrapper, no external API calls in dry-run/doctor/tests. +- Create `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: offline unit tests for paths, credential redaction, install dry-run, dirty upstream, command construction, and direct fallback routing expectations. +- Create `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml`: tracked example config for upstream URL/ref and runtime defaults. +- Create `skills/AI4Math-Lean-Agents/references/numina_runtime.md`: operator reference for official Numina deployment and invocation. +- Modify `skills/AI4Math-Lean-Agents/scripts/common.py`: add `numina-runtime/` to `.ai4math/.gitignore`; keep existing `.env.local` behavior. +- Modify `skills/AI4Math-Lean-Agents/scripts/configure_lean.py`: include Numina readiness summary in `inspect_environment`; add `setup_numina`, `project_name`, and `skip_numina_sync` arguments to `configure`. +- Modify `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: include `uv`, `curl`, and `claude` in tool reporting. +- Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py`: add Numina task-plan builder while preserving direct builder for `--direct`. +- Modify `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: add `numina-*` commands, wire `configure --setup-numina`, add `--direct` to task commands, update exit-code mapping. +- Modify `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py`: require new files and commands; update guidance-first text checks for Numina runtime workflow. +- Modify docs: `skills/AI4Math-Lean-Agents/SKILL.md`, `README.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `skills/AI4Math-Lean-Agents/agents/openai.yaml`, `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`. + +--- + +### Task 1: Runtime Paths, Local Env, and Gitignore + +**Files:** +- Create: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` +- Create: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` +- Modify: `skills/AI4Math-Lean-Agents/scripts/common.py` + +- [ ] **Step 1: Write failing tests for runtime path defaults and gitignore** + +Add this to `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: + +```python +from __future__ import annotations + +import os +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPTS)) + +from common import ensure_ai4math_gitignore # noqa: E402 +from numina_runtime import ( # noqa: E402 + DEFAULT_UPSTREAM_URL, + credential_report, + read_numina_env_local, + runtime_paths, +) + + +class NuminaRuntimePathTests(unittest.TestCase): + def test_runtime_paths_default_under_ai4math(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + paths = runtime_paths(Path(tmp)) + + self.assertEqual(paths["root"], str(Path(tmp).resolve() / ".ai4math" / "numina-runtime")) + self.assertEqual(paths["upstream"], str(Path(tmp).resolve() / ".ai4math" / "numina-runtime" / "upstream")) + self.assertEqual(paths["results"], str(Path(tmp).resolve() / ".ai4math" / "numina-runtime" / "results")) + self.assertEqual(paths["default_upstream_url"], DEFAULT_UPSTREAM_URL) + + def test_runtime_paths_honor_ai4math_numina_home(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + custom = Path(tmp) / "custom-numina" + with patch.dict(os.environ, {"AI4MATH_NUMINA_HOME": str(custom)}, clear=False): + paths = runtime_paths(Path(tmp)) + + self.assertEqual(paths["root"], str(custom.resolve())) + self.assertEqual(paths["upstream"], str(custom.resolve() / "upstream")) + + def test_numina_runtime_is_ignored(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + gitignore = ensure_ai4math_gitignore(tmp) + + lines = gitignore.read_text(encoding="utf-8").splitlines() + + self.assertIn("numina-runtime/", lines) + + +class NuminaRuntimeCredentialTests(unittest.TestCase): + def test_env_local_is_read_from_numina_runtime_root(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + env_path = Path(tmp) / ".ai4math" / "numina-runtime" / ".env.local" + env_path.parent.mkdir(parents=True) + env_path.write_text( + "export ANTHROPIC_AUTH_TOKEN=secret-token\n" + "OPENAI_API_KEY=sk-test\n", + encoding="utf-8", + ) + + values = read_numina_env_local(Path(tmp)) + + self.assertEqual(values["ANTHROPIC_AUTH_TOKEN"], "secret-token") + self.assertEqual(values["OPENAI_API_KEY"], "sk-test") + + def test_credential_report_redacts_values(self) -> None: + env = { + "ANTHROPIC_AUTH_TOKEN": "secret-token", + "OPENAI_API_KEY": "sk-test", + } + + report = credential_report(env) + + self.assertTrue(report["claude"]["configured"]) + self.assertEqual(report["claude"]["variables"]["ANTHROPIC_AUTH_TOKEN"], "") + self.assertEqual(report["skill_keys"]["OPENAI_API_KEY"], "") + self.assertNotIn("secret-token", str(report)) + + +if __name__ == "__main__": + unittest.main() +``` + +- [ ] **Step 2: Run the new tests to verify they fail** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +``` + +Expected: FAIL with `ModuleNotFoundError: No module named 'numina_runtime'` or missing function imports. + +- [ ] **Step 3: Implement minimal runtime path and credential helpers** + +Create `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: + +```python +from __future__ import annotations + +import os +import shlex +from pathlib import Path +from typing import Any + +from common import expand_path + + +DEFAULT_UPSTREAM_URL = "https://github.com/project-numina/numina-lean-agent" +CLAUDE_ENV_KEYS = ["ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL", "ANTHROPIC_MODEL"] +SKILL_ENV_KEYS = ["GEMINI_API_KEY", "OPENAI_API_KEY", "LEAN_LEANDEX_API_KEY", "AXLE_API_KEY"] + + +def runtime_root(cwd: str | Path) -> Path: + cwd_path = Path(cwd).resolve() + override = os.environ.get("AI4MATH_NUMINA_HOME") + if override: + return expand_path(override, cwd_path) or (cwd_path / ".ai4math" / "numina-runtime") + return cwd_path / ".ai4math" / "numina-runtime" + + +def runtime_paths(cwd: str | Path) -> dict[str, str]: + root = runtime_root(cwd) + return { + "root": str(root), + "upstream": str(root / "upstream"), + "projects": str(root / "projects"), + "results": str(root / "results"), + "env_local": str(root / ".env.local"), + "local_config": str(root / "numina_runtime.local.toml"), + "default_upstream_url": DEFAULT_UPSTREAM_URL, + } + + +def _parse_env_file(path: Path) -> dict[str, str]: + if not path.exists(): + return {} + values: dict[str, str] = {} + for raw_line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + parts = shlex.split(line, comments=True, posix=True) + if parts and parts[0] == "export": + parts = parts[1:] + for part in parts: + if "=" in part: + key, value = part.split("=", 1) + values[key] = value + return values + + +def read_numina_env_local(cwd: str | Path) -> dict[str, str]: + return _parse_env_file(runtime_root(cwd) / ".env.local") + + +def _redact(value: str | None) -> str | None: + return "" if value else None + + +def credential_report(env: dict[str, str] | None = None) -> dict[str, Any]: + merged = dict(os.environ) + if env: + merged.update(env) + claude_variables = {key: _redact(merged.get(key)) for key in CLAUDE_ENV_KEYS} + skill_keys = {key: _redact(merged.get(key)) for key in SKILL_ENV_KEYS} + return { + "claude": { + "configured": bool(merged.get("ANTHROPIC_AUTH_TOKEN")), + "variables": claude_variables, + }, + "skill_keys": skill_keys, + "missing_skill_keys": [key for key in SKILL_ENV_KEYS if not merged.get(key)], + } +``` + +Modify `ensure_ai4math_gitignore` in `skills/AI4Math-Lean-Agents/scripts/common.py` so the `entries` list includes: + +```python + "numina-runtime/", +``` + +- [ ] **Step 4: Run the focused tests to verify they pass** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +``` + +Expected: PASS. + +- [ ] **Step 5: Commit Task 1** + +```bash +git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ + skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py \ + skills/AI4Math-Lean-Agents/scripts/common.py +git commit -m "Add Numina runtime path helpers" +``` + +--- + +### Task 2: Upstream Status, Doctor, and Install Dry-Run + +**Files:** +- Modify: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` +- Modify: `skills/AI4Math-Lean-Agents/scripts/tool_status.py` + +- [ ] **Step 1: Add failing tests for upstream status and install planning** + +Append to `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: + +```python +from numina_runtime import build_install_plan, inspect_upstream, numina_doctor # noqa: E402 + + +class NuminaRuntimeInstallTests(unittest.TestCase): + def test_install_dry_run_clones_official_upstream_when_missing(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = build_install_plan(Path(tmp), dry_run=True) + + self.assertTrue(result["ok"]) + self.assertEqual(result["status"], "dry_run") + self.assertEqual(result["upstream_url"], DEFAULT_UPSTREAM_URL) + self.assertEqual(result["actions"][0]["command"][:2], ["git", "clone"]) + self.assertIn(DEFAULT_UPSTREAM_URL, result["actions"][0]["command"]) + + def test_dirty_upstream_blocks_update(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + upstream = Path(tmp) / ".ai4math" / "numina-runtime" / "upstream" + upstream.mkdir(parents=True) + (upstream / ".git").mkdir() + with patch("numina_runtime.run_command") as run: + run.return_value = {"ok": True, "stdout": " M file.py\n", "stderr": "", "returncode": 0} + + result = build_install_plan(Path(tmp), dry_run=False) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "upstream_dirty") + + def test_doctor_reports_missing_upstream_without_installing(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = numina_doctor(Path(tmp)) + + self.assertTrue(result["ok"]) + self.assertEqual(result["status"], "reported") + self.assertFalse(result["numina"]["upstream"]["exists"]) + self.assertIn("numina-install", result["recommended_next_action"]) +``` + +- [ ] **Step 2: Run tests to verify they fail** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +``` + +Expected: FAIL with missing `build_install_plan`, `inspect_upstream`, or `numina_doctor`. + +- [ ] **Step 3: Implement upstream inspection and dry-run install planning** + +Add these imports to `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: + +```python +from common import run_command +from tool_status import find_tool, tool_versions +``` + +Add these functions: + +```python +def upstream_url() -> str: + return os.environ.get("NUMINA_LEAN_AGENT_REPO") or DEFAULT_UPSTREAM_URL + + +def upstream_ref() -> str | None: + return os.environ.get("NUMINA_LEAN_AGENT_REF") or None + + +def inspect_upstream(cwd: str | Path) -> dict[str, Any]: + upstream = runtime_root(cwd) / "upstream" + exists = upstream.exists() + is_git = (upstream / ".git").exists() + result: dict[str, Any] = { + "path": str(upstream), + "exists": exists, + "is_git": is_git, + "dirty": False, + "commit": None, + } + if not is_git: + return result + status = run_command(["git", "status", "--short"], cwd=upstream, timeout=30) + result["dirty"] = bool((status.get("stdout") or "").strip()) + rev = run_command(["git", "rev-parse", "HEAD"], cwd=upstream, timeout=30) + if rev.get("ok"): + result["commit"] = (rev.get("stdout") or "").strip() + return result + + +def _install_commands(cwd: str | Path) -> list[dict[str, Any]]: + paths = runtime_paths(cwd) + upstream = paths["upstream"] + url = upstream_url() + ref = upstream_ref() + actions: list[dict[str, Any]] = [] + if not Path(upstream).exists(): + actions.append({"command": ["git", "clone", url, upstream], "cwd": str(Path(cwd).resolve())}) + else: + actions.append({"command": ["git", "fetch", "--all", "--tags"], "cwd": upstream}) + if ref: + actions.append({"command": ["git", "checkout", ref], "cwd": upstream}) + return actions + + +def build_install_plan(cwd: str | Path, dry_run: bool = False) -> dict[str, Any]: + info = inspect_upstream(cwd) + if info["exists"] and info["is_git"] and info["dirty"] and not dry_run: + return { + "ok": False, + "status": "upstream_dirty", + "upstream": info, + "recommended_next_action": "commit, stash, or clean the upstream checkout before updating", + } + actions = _install_commands(cwd) + if dry_run: + return { + "ok": True, + "status": "dry_run", + "upstream_url": upstream_url(), + "upstream_ref": upstream_ref(), + "actions": actions, + } + return { + "ok": True, + "status": "install_plan_ready", + "upstream_url": upstream_url(), + "upstream_ref": upstream_ref(), + "actions": actions, + } + + +def numina_doctor(cwd: str | Path, target: str | Path | None = None) -> dict[str, Any]: + env_local = read_numina_env_local(cwd) + upstream = inspect_upstream(cwd) + missing = [] + if not upstream["exists"]: + missing.append("numina_runtime") + return { + "ok": True, + "status": "reported", + "cwd": str(Path(cwd).resolve()), + "tools": tool_versions(["git", "curl", "uv", "elan", "lean", "lake", "claude", "python3"]), + "credentials": credential_report(env_local), + "numina": { + "runtime_paths": runtime_paths(cwd), + "upstream": upstream, + }, + "missing": missing, + "recommended_next_action": "run numina-install --dry-run, then numina-install" if missing else "ready for numina-configure or numina-run", + } +``` + +- [ ] **Step 4: Update tool status defaults** + +Modify `DEFAULT_TOOLS` in `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: + +```python +DEFAULT_TOOLS = ["git", "python3", "curl", "uv", "elan", "lean", "lake", "claude"] +``` + +- [ ] **Step 5: Run focused tests** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +``` + +Expected: PASS. + +- [ ] **Step 6: Commit Task 2** + +```bash +git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ + skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py \ + skills/AI4Math-Lean-Agents/scripts/tool_status.py +git commit -m "Add Numina runtime doctor and install plan" +``` + +--- + +### Task 3: Numina Configure and Runner Command Plans + +**Files:** +- Modify: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` + +- [ ] **Step 1: Add failing tests for configure/run/from-folder/batch plans** + +Append to `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: + +```python +from numina_runtime import ( # noqa: E402 + build_batch_plan, + build_configure_plan, + build_from_folder_plan, + build_run_plan, +) + + +class NuminaRuntimeCommandPlanTests(unittest.TestCase): + def make_lake_project(self, root: Path) -> Path: + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + source = root / "Main.lean" + source.write_text("example : True := by trivial\n", encoding="utf-8") + return source + + def make_upstream(self, root: Path) -> Path: + upstream = root / ".ai4math" / "numina-runtime" / "upstream" + upstream.mkdir(parents=True) + (upstream / ".git").mkdir() + return upstream + + def test_configure_plan_runs_setup_and_uv_sync(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + self.make_upstream(root) + + result = build_configure_plan(root, project_name="myproofs", skip_sync=False, dry_run=True) + + self.assertTrue(result["ok"]) + commands = [action["command"] for action in result["actions"]] + self.assertIn(["./setup.sh", "myproofs"], commands) + self.assertIn(["uv", "python", "install"], commands) + self.assertIn(["uv", "sync"], commands) + + def test_run_plan_requires_lake_project(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + target = root / "Main.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + + result = build_run_plan(root, target, prompt_file=None, prompt="prove it", max_rounds=5, result_dir=None, dry_run=True) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "missing_lake_project") + + def test_run_plan_builds_upstream_runner_command(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + self.make_upstream(root) + target = self.make_lake_project(root) + prompt = root / "prompt.md" + prompt.write_text("prove the target\n", encoding="utf-8") + + result = build_run_plan(root, target, prompt_file=prompt, prompt=None, max_rounds=7, result_dir=None, dry_run=True) + + self.assertTrue(result["ok"]) + self.assertEqual(result["status"], "dry_run") + command = result["command"] + self.assertEqual(command[:4], ["python", "-m", "scripts.run_claude", "run"]) + self.assertIn("--max-rounds", command) + self.assertIn("7", command) + + def test_from_folder_plan_builds_command(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + self.make_upstream(root) + self.make_lake_project(root) + + result = build_from_folder_plan(root, root, prompt_file=None, max_rounds=3, result_dir=None, dry_run=True) + + self.assertTrue(result["ok"]) + self.assertEqual(result["command"][:4], ["python", "-m", "scripts.run_claude", "from-folder"]) + + def test_batch_plan_requires_config(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = build_batch_plan(Path(tmp), Path(tmp) / "missing.yaml", dry_run=True) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "file_not_found") +``` + +- [ ] **Step 2: Run tests to verify they fail** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +``` + +Expected: FAIL with missing plan functions. + +- [ ] **Step 3: Implement configure and runner plan functions** + +Add to `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: + +```python +from check_lean_project import find_project_root + + +def _upstream_path(cwd: str | Path) -> Path: + return Path(runtime_paths(cwd)["upstream"]) + + +def _default_result_dir(cwd: str | Path, task_type: str) -> Path: + root = Path(runtime_paths(cwd)["results"]) + return root / task_type + + +def build_configure_plan( + cwd: str | Path, + project_name: str, + skip_sync: bool = False, + dry_run: bool = False, +) -> dict[str, Any]: + upstream = _upstream_path(cwd) + if not upstream.exists(): + return { + "ok": False, + "status": "missing_numina_runtime", + "recommended_next_action": "run numina-install first", + } + actions = [ + {"command": ["./setup.sh", project_name], "cwd": str(upstream / "tutorial")}, + ] + if not skip_sync: + actions.extend([ + {"command": ["uv", "python", "install"], "cwd": str(upstream)}, + {"command": ["uv", "sync"], "cwd": str(upstream)}, + ]) + return { + "ok": True, + "status": "dry_run" if dry_run else "configure_plan_ready", + "project_name": project_name, + "actions": actions, + } + + +def _validate_lake_target(path: Path) -> tuple[Path | None, dict[str, Any] | None]: + root = find_project_root(path) + if root is None: + return None, {"ok": False, "status": "missing_lake_project", "target": str(path)} + return root, None + + +def build_run_plan( + cwd: str | Path, + file: str | Path, + prompt_file: str | Path | None, + prompt: str | None, + max_rounds: int, + result_dir: str | Path | None, + dry_run: bool = False, +) -> dict[str, Any]: + target = Path(file).expanduser().resolve() + if not target.exists(): + return {"ok": False, "status": "file_not_found", "target": str(target)} + project_root, error = _validate_lake_target(target) + if error: + return error + upstream = _upstream_path(cwd) + if not upstream.exists(): + return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run numina-install"} + if prompt_file is None and not prompt: + return {"ok": False, "status": "missing_prompt"} + output_dir = Path(result_dir).expanduser().resolve() if result_dir else _default_result_dir(cwd, "run") + command = ["python", "-m", "scripts.run_claude", "run", str(target)] + if prompt_file: + command.extend(["--prompt-file", str(Path(prompt_file).expanduser().resolve())]) + if prompt: + command.extend(["--prompt", prompt]) + command.extend(["--max-rounds", str(max_rounds), "--result-dir", str(output_dir)]) + return { + "ok": True, + "status": "dry_run" if dry_run else "numina_run_ready", + "command": command, + "cwd": str(upstream), + "project_root": str(project_root), + "result_dir": str(output_dir), + } + + +def build_from_folder_plan( + cwd: str | Path, + folder: str | Path, + prompt_file: str | Path | None, + max_rounds: int, + result_dir: str | Path | None, + dry_run: bool = False, +) -> dict[str, Any]: + folder_path = Path(folder).expanduser().resolve() + if not folder_path.exists(): + return {"ok": False, "status": "file_not_found", "target": str(folder_path)} + project_root, error = _validate_lake_target(folder_path) + if error: + return error + upstream = _upstream_path(cwd) + if not upstream.exists(): + return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run numina-install"} + output_dir = Path(result_dir).expanduser().resolve() if result_dir else _default_result_dir(cwd, "from-folder") + command = ["python", "-m", "scripts.run_claude", "from-folder", str(folder_path)] + if prompt_file: + command.extend(["--prompt-file", str(Path(prompt_file).expanduser().resolve())]) + command.extend(["--max-rounds", str(max_rounds), "--result-dir", str(output_dir)]) + return { + "ok": True, + "status": "dry_run" if dry_run else "numina_from_folder_ready", + "command": command, + "cwd": str(upstream), + "project_root": str(project_root), + "result_dir": str(output_dir), + } + + +def build_batch_plan(cwd: str | Path, config: str | Path, dry_run: bool = False) -> dict[str, Any]: + config_path = Path(config).expanduser().resolve() + if not config_path.exists(): + return {"ok": False, "status": "file_not_found", "config": str(config_path)} + upstream = _upstream_path(cwd) + if not upstream.exists(): + return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run numina-install"} + command = ["python", "-m", "scripts.run_claude", "batch", str(config_path)] + return { + "ok": True, + "status": "dry_run" if dry_run else "numina_batch_ready", + "command": command, + "cwd": str(upstream), + } +``` + +- [ ] **Step 4: Run focused tests** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +``` + +Expected: PASS. + +- [ ] **Step 5: Commit Task 3** + +```bash +git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ + skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +git commit -m "Add Numina runtime command planning" +``` + +--- + +### Task 4: Wire Numina Commands into `ai4m_lean.py` + +**Files:** +- Modify: `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` + +- [ ] **Step 1: Add failing CLI tests for new parser commands** + +Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: + +```python + def test_numina_install_dry_run_outputs_official_upstream(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = subprocess.run( + [sys.executable, str(CLI), "numina-install", "--cwd", tmp, "--dry-run"], + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertEqual(payload["status"], "dry_run") + self.assertEqual(payload["upstream_url"], "https://github.com/project-numina/numina-lean-agent") + + def test_numina_doctor_reports_missing_runtime(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = subprocess.run( + [sys.executable, str(CLI), "numina-doctor", "--cwd", tmp], + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertEqual(payload["status"], "reported") + self.assertIn("numina_runtime", payload["missing"]) +``` + +- [ ] **Step 2: Run CLI tests to verify they fail** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_cli.py +``` + +Expected: FAIL because `numina-install` and `numina-doctor` are invalid subcommands. + +- [ ] **Step 3: Add imports and parser entries** + +Modify imports in `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: + +```python +from numina_runtime import ( + build_batch_plan, + build_configure_plan, + build_from_folder_plan, + build_install_plan, + build_run_plan, + numina_doctor, +) +``` + +Add a helper near `add_common`: + +```python +def add_numina_common(parser: argparse.ArgumentParser) -> None: + add_common(parser) + parser.add_argument("--dry-run", action="store_true") +``` + +Add parser definitions in `build_parser()`: + +```python + numina_doctor_parser = sub.add_parser("numina-doctor", help="Report official Numina runtime readiness") + add_common(numina_doctor_parser) + numina_doctor_parser.add_argument("--target", default=None) + + numina_install = sub.add_parser("numina-install", help="Clone or update official Numina Lean Agent") + add_numina_common(numina_install) + + numina_configure = sub.add_parser("numina-configure", help="Run upstream Numina tutorial setup") + add_numina_common(numina_configure) + numina_configure.add_argument("--project-name", required=True) + numina_configure.add_argument("--skip-sync", action="store_true") + + numina_run = sub.add_parser("numina-run", help="Run official Numina on one Lean file") + add_numina_common(numina_run) + numina_run.add_argument("--file", required=True) + numina_run.add_argument("--prompt-file", default=None) + numina_run.add_argument("--prompt", default=None) + numina_run.add_argument("--max-rounds", type=int, default=5) + numina_run.add_argument("--result-dir", default=None) + + numina_folder = sub.add_parser("numina-from-folder", help="Run official Numina on a folder") + add_numina_common(numina_folder) + numina_folder.add_argument("--folder", required=True) + numina_folder.add_argument("--prompt-file", default=None) + numina_folder.add_argument("--max-rounds", type=int, default=5) + numina_folder.add_argument("--result-dir", default=None) + + numina_batch = sub.add_parser("numina-batch", help="Run official Numina batch config") + add_numina_common(numina_batch) + numina_batch.add_argument("--config-file", "--config", dest="batch_config", required=True) +``` + +- [ ] **Step 4: Add command dispatch** + +In `main()`, before existing task dispatch, add: + +```python + if args.command == "numina-doctor": + result = numina_doctor(args.cwd, target=args.target) + _finish(result, args.json_output) + + if args.command == "numina-install": + result = build_install_plan(args.cwd, dry_run=args.dry_run) + _finish(result, args.json_output) + + if args.command == "numina-configure": + result = build_configure_plan( + args.cwd, + project_name=args.project_name, + skip_sync=args.skip_sync, + dry_run=args.dry_run, + ) + _finish(result, args.json_output) + + if args.command == "numina-run": + result = build_run_plan( + args.cwd, + args.file, + prompt_file=args.prompt_file, + prompt=args.prompt, + max_rounds=args.max_rounds, + result_dir=args.result_dir, + dry_run=args.dry_run, + ) + _finish(result, args.json_output) + + if args.command == "numina-from-folder": + result = build_from_folder_plan( + args.cwd, + args.folder, + prompt_file=args.prompt_file, + max_rounds=args.max_rounds, + result_dir=args.result_dir, + dry_run=args.dry_run, + ) + _finish(result, args.json_output) + + if args.command == "numina-batch": + result = build_batch_plan(args.cwd, args.batch_config, dry_run=args.dry_run) + _finish(result, args.json_output) +``` + +- [ ] **Step 5: Run CLI tests** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_cli.py +``` + +Expected: PASS. + +- [ ] **Step 6: Commit Task 4** + +```bash +git add skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ + skills/AI4Math-Lean-Agents/tests/test_cli.py +git commit -m "Wire Numina runtime CLI commands" +``` + +--- + +### Task 5: Default Task Commands Use Numina, `--direct` Preserves Old Behavior + +**Files:** +- Modify: `skills/AI4Math-Lean-Agents/scripts/direct_task.py` +- Modify: `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_direct_task.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` + +- [ ] **Step 1: Add failing tests for Numina default and direct fallback** + +Append to `skills/AI4Math-Lean-Agents/tests/test_direct_task.py`: + +```python +from direct_task import build_numina_task # noqa: E402 + + +class NuminaTaskRoutingTests(unittest.TestCase): + def test_numina_task_dry_run_reports_missing_runtime(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + target = root / "Main.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + + result = build_numina_task("repair", root, target, max_rounds=5, prompt_file=None, result_dir=None, dry_run=True) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "missing_numina_runtime") + self.assertEqual(result["backend"], "official-numina") +``` + +Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: + +```python + def test_repair_direct_preserves_old_task_envelope(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + target = root / "Main.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + result = subprocess.run( + [sys.executable, str(CLI), "repair", "--cwd", str(root), "--file", str(target), "--dry-run", "--direct"], + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertEqual(payload["agent_mode"], "direct-coding-agent") + self.assertEqual(payload["backend"], "none") + + def test_repair_default_routes_to_numina(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + target = root / "Main.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + result = subprocess.run( + [sys.executable, str(CLI), "repair", "--cwd", str(root), "--file", str(target), "--dry-run"], + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(result.returncode, 4, result.stderr) + payload = json.loads(result.stdout) + self.assertEqual(payload["backend"], "official-numina") + self.assertEqual(payload["status"], "missing_numina_runtime") +``` + +- [ ] **Step 2: Run tests to verify they fail** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest \ + skills/AI4Math-Lean-Agents/tests/test_direct_task.py \ + skills/AI4Math-Lean-Agents/tests/test_cli.py +``` + +Expected: FAIL with missing `build_numina_task` and unknown `--direct`. + +- [ ] **Step 3: Implement Numina task builder** + +Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py`: + +```python +from numina_runtime import build_batch_plan, build_run_plan +``` + +Add: + +```python +def build_numina_task( + task_type: str, + cwd: str | Path, + target: str | Path, + max_rounds: int = 5, + prompt_file: str | Path | None = None, + result_dir: str | Path | None = None, + dry_run: bool = False, +) -> dict[str, Any]: + if task_type == "batch": + result = build_batch_plan(cwd, target, dry_run=dry_run) + else: + result = build_run_plan( + cwd, + target, + prompt_file=prompt_file, + prompt=None, + max_rounds=max_rounds, + result_dir=result_dir, + dry_run=dry_run, + ) + result.setdefault("task_type", task_type) + result["agent_mode"] = "numina-runtime" + result["backend"] = "official-numina" + return result +``` + +- [ ] **Step 4: Wire `--direct` in CLI task commands** + +In `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`, import: + +```python +from direct_task import run_direct_task, build_numina_task +``` + +Add `--direct` to proof and batch parsers: + +```python + proof.add_argument("--direct", action="store_true", help="Use direct local Lean task envelope instead of official Numina") +``` + +For `batch`: + +```python + batch.add_argument("--direct", action="store_true", help="Use direct local Lean batch envelope instead of official Numina") +``` + +Change task dispatch: + +```python + if args.command in {"prove", "formalize", "repair", "complete-sorries"}: + if args.direct: + result = run_direct_task(...) + else: + result = build_numina_task( + args.command, + cwd=args.cwd, + target=args.file, + max_rounds=args.max_rounds, + prompt_file=args.prompt_file, + result_dir=args.result_dir, + dry_run=args.dry_run, + ) + ... +``` + +For `batch`, route to `build_numina_task("batch", ...)` unless `args.direct` is set. + +- [ ] **Step 5: Update exit-code mapping for missing Numina runtime** + +Modify `_exit_code` in `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: + +```python + if status in {"missing_config", "direct_task_missing_config", "missing_numina_runtime", "missing_numina_credentials"}: + return EXIT_MISSING_CONFIG +``` + +- [ ] **Step 6: Run focused tests** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest \ + skills/AI4Math-Lean-Agents/tests/test_direct_task.py \ + skills/AI4Math-Lean-Agents/tests/test_cli.py +``` + +Expected: PASS. + +- [ ] **Step 7: Commit Task 5** + +```bash +git add skills/AI4Math-Lean-Agents/scripts/direct_task.py \ + skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ + skills/AI4Math-Lean-Agents/tests/test_direct_task.py \ + skills/AI4Math-Lean-Agents/tests/test_cli.py +git commit -m "Route task commands through Numina runtime" +``` + +--- + +### Task 6: Configure Integration and Environment Readiness + +**Files:** +- Modify: `skills/AI4Math-Lean-Agents/scripts/configure_lean.py` +- Modify: `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py` + +- [ ] **Step 1: Add failing tests for Numina readiness in environment inspection** + +Append to `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py`: + +```python + def test_inspect_environment_includes_numina_runtime_summary(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = inspect_environment(tmp) + + self.assertIn("numina", result) + self.assertFalse(result["numina"]["upstream"]["exists"]) + self.assertIn("numina-install", result["numina"]["recommended_next_action"]) +``` + +- [ ] **Step 2: Run tests to verify they fail** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_configure_lean.py +``` + +Expected: FAIL because `numina` key is absent. + +- [ ] **Step 3: Add Numina summary to `inspect_environment`** + +Modify `skills/AI4Math-Lean-Agents/scripts/configure_lean.py` imports: + +```python +from numina_runtime import numina_doctor, build_configure_plan, build_install_plan +``` + +In `inspect_environment`, before return: + +```python + numina = numina_doctor(cwd_path, target=target_path) +``` + +Add to returned dict: + +```python + "numina": { + "status": numina.get("status"), + "upstream": numina.get("numina", {}).get("upstream"), + "runtime_paths": numina.get("numina", {}).get("runtime_paths"), + "missing": numina.get("missing", []), + "recommended_next_action": numina.get("recommended_next_action"), + }, +``` + +- [ ] **Step 4: Add configure `--setup-numina` support** + +Change `configure()` signature: + +```python +def configure(..., setup_numina: bool = False, project_name: str | None = None, skip_numina_sync: bool = False) -> dict[str, Any]: +``` + +Inside `configure`, after workspace handling: + +```python + numina_actions: list[dict[str, Any]] = [] + if setup_numina: + install = build_install_plan(cwd_path, dry_run=dry_run) + numina_actions.append(install) + if install.get("ok") and project_name: + numina_actions.append(build_configure_plan(cwd_path, project_name, skip_sync=skip_numina_sync, dry_run=dry_run)) +``` + +Before return: + +```python + env["numina_actions"] = numina_actions +``` + +In `ai4m_lean.py`, add parser args to `configure`: + +```python + configure_parser.add_argument("--setup-numina", action="store_true") + configure_parser.add_argument("--project-name", default=None) + configure_parser.add_argument("--skip-numina-sync", action="store_true") +``` + +Pass them to `configure()`. + +- [ ] **Step 5: Run configure tests** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_configure_lean.py +``` + +Expected: PASS. + +- [ ] **Step 6: Commit Task 6** + +```bash +git add skills/AI4Math-Lean-Agents/scripts/configure_lean.py \ + skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ + skills/AI4Math-Lean-Agents/tests/test_configure_lean.py +git commit -m "Add Numina runtime configure integration" +``` + +--- + +### Task 7: Config, Reference, and Skill Documentation + +**Files:** +- Create: `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml` +- Create: `skills/AI4Math-Lean-Agents/references/numina_runtime.md` +- Modify: `skills/AI4Math-Lean-Agents/SKILL.md` +- Modify: `skills/AI4Math-Lean-Agents/agents/openai.yaml` +- Modify: `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md` +- Modify: `README.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` + +- [ ] **Step 1: Add runtime example config** + +Create `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml`: + +```toml +[numina] +upstream_url = "https://github.com/project-numina/numina-lean-agent" +runtime_root = ".ai4math/numina-runtime" +default_ref = "main" +results_dir = ".ai4math/numina-runtime/results" +sync_dependencies_by_default = true + +[credentials] +read_env_local = true +env_local_path = ".ai4math/numina-runtime/.env.local" +``` + +- [ ] **Step 2: Add runtime reference** + +Create `skills/AI4Math-Lean-Agents/references/numina_runtime.md`: + +```markdown +# Numina Runtime Workflow + +Use this reference when the user wants official Numina deployment or invocation. + +## First-Time Setup + +Run: + +```bash +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-doctor --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . --dry-run +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-configure --cwd . --project-name myproofs +``` + +## Invocation + +Run one file: + +```bash +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-run --cwd . --file path/to/Foo.lean --prompt-file path/to/prompt.md +``` + +Run a task command through the default Numina route: + +```bash +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file path/to/Foo.lean --prompt-file path/to/prompt.md +``` + +Use the old direct local task envelope only when explicitly requested: + +```bash +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file path/to/Foo.lean --direct --dry-run +``` + +## Safety + +The Numina route may call external model APIs through upstream Numina and Claude. Never print secret values. Use `.ai4math/numina-runtime/.env.local` or the shell environment for credentials. +``` + +- [ ] **Step 3: Rewrite `SKILL.md` runtime sections** + +Modify `skills/AI4Math-Lean-Agents/SKILL.md` so the opening says: + +```markdown +AI4Math Lean Agents uses an official Numina runtime assisted workflow by default. The skill can fetch `project-numina/numina-lean-agent`, configure local dependencies, call upstream Numina runners, and then use local Lean/Lake guardrails for validation, patch review, `sorry` detection, and minimal failure handoff. +``` + +Replace the old “Numina is not deployed or called” rule with: + +```markdown +Official Numina may be deployed and called when the user requests proof repair, theorem proving, formalization, `sorry` completion, or batch Lean work. Direct local Lean editing remains available as a fallback via `--direct` and for validation/review tasks. +``` + +Add `references/numina_runtime.md` to the References list. + +- [ ] **Step 4: Update root-facing docs** + +Update these files consistently: + +- `README.md`: describe default Numina runtime, new `numina-*` commands, external API caveat. +- `AGENTS.md`: instruct agents to use `AI4Math-Lean-Agents/SKILL.md`, deploy/call official Numina by default, and keep direct guardrails. +- `CLAUDE.md`: same as AGENTS, with Claude CLI credential note. +- `GEMINI.md`: same policy wording for Gemini. +- `skills/AI4Math-Lean-Agents/agents/openai.yaml`: update `short_description` and `default_prompt` to mention official Numina runtime. +- `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`: add a top note saying it is historical background and no longer defines the no-call policy. + +- [ ] **Step 5: Commit Task 7** + +```bash +git add README.md AGENTS.md CLAUDE.md GEMINI.md \ + skills/AI4Math-Lean-Agents/SKILL.md \ + skills/AI4Math-Lean-Agents/agents/openai.yaml \ + skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml \ + skills/AI4Math-Lean-Agents/references/numina_runtime.md \ + skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md +git commit -m "Update skill docs for official Numina runtime" +``` + +--- + +### Task 8: Delivery Verification and Full Test Pass + +**Files:** +- Modify: `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` + +- [ ] **Step 1: Update required delivery files and commands** + +Modify `REQUIRED_FILES` in `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py` to include: + +```python + "config/numina_runtime.example.toml", + "references/numina_runtime.md", + "scripts/numina_runtime.py", +``` + +Modify `REQUIRED_COMMANDS` to include: + +```python + "numina-doctor", + "numina-install", + "numina-configure", + "numina-run", + "numina-from-folder", + "numina-batch", +``` + +- [ ] **Step 2: Update guidance check** + +Replace `_guidance_first_check()` required phrases with phrases matching the new policy: + +```python + required_phrases = [ + "## Agent Playbook", + "## Helper Toolbox", + "official Numina runtime", + "Direct local Lean editing remains available as a fallback via `--direct`", + ] +``` + +Update `external_api_note` in `verify()`: + +```python + "external_api_note": "The default Numina runtime workflow may call upstream Numina, Claude, and external model APIs. Guardrail commands and default tests remain local/offline.", +``` + +- [ ] **Step 3: Add CLI delivery expectation** + +In `skills/AI4Math-Lean-Agents/tests/test_cli.py`, update `test_verify_delivery_package_checks`: + +```python + self.assertIn("numina-install", payload["commands"]["available"]) + self.assertIn("scripts/numina_runtime.py", [item["path"] for item in payload["files"]]) +``` + +- [ ] **Step 4: Run package tests** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/AI4Math-Lean-Agents/tests +``` + +Expected: all tests pass. + +- [ ] **Step 5: Run delivery verification** + +Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +``` + +Expected: JSON has `"ok": true`, `"status": "delivery_ready"`, and `"unit_tests": {"ok": true, ...}`. + +- [ ] **Step 6: Commit Task 8** + +```bash +git add skills/AI4Math-Lean-Agents/scripts/verify_delivery.py \ + skills/AI4Math-Lean-Agents/tests/test_cli.py +git commit -m "Verify Numina runtime delivery" +``` + +--- + +## Final Verification Checklist + +- [ ] Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/AI4Math-Lean-Agents/tests +``` + +Expected: all tests pass. + +- [ ] Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +``` + +Expected: `"ok": true` and `"status": "delivery_ready"`. + +- [ ] Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . --dry-run +``` + +Expected: JSON includes `"status": "dry_run"` and `"upstream_url": "https://github.com/project-numina/numina-lean-agent"`. + +- [ ] Run: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-doctor --cwd . +``` + +Expected: JSON includes `numina.runtime_paths`, `credentials`, and no secret values. + +- [ ] Run: + +```bash +git status --short +``` + +Expected: no unstaged or uncommitted implementation changes. + +--- + +## Self-Review Notes + +- Spec coverage: The plan covers existing-skill modification, official upstream install/dry-run, runtime state, CLI commands, task routing, `--direct`, docs, tests, delivery verifier, and external API disclosure. +- Completeness scan: The plan uses concrete code snippets, exact commands, expected outputs, and no open-ended steps. +- Type consistency: Runtime status names use the spec vocabulary: `missing_numina_runtime`, `upstream_dirty`, `numina_run_ready`, and `direct_task_ready`. From c13be620a7a39ab8078f31086feb5334abd8d086 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 21:35:01 +0800 Subject: [PATCH 07/37] Simplify Numina runtime CLI plan --- .../2026-05-24-ai4math-numina-runtime.md | 947 ++++++------------ ...-05-24-numina-lean-agent-runtime-design.md | 69 +- 2 files changed, 337 insertions(+), 679 deletions(-) diff --git a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md index 5137a4b..3fedec0 100644 --- a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md +++ b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md @@ -2,9 +2,9 @@ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** 改造现有 `AI4Math-Lean-Agents` skill,使其能自动部署并调用官方 `project-numina/numina-lean-agent`,同时保留现有 Lean guardrails 和 direct fallback。 +**Goal:** 改造现有 `AI4Math-Lean-Agents` skill,使其通过现有 CLI 自动部署并调用官方 `project-numina/numina-lean-agent`,同时保留现有 Lean guardrails 和 `--direct` fallback。 -**Architecture:** 新增 `scripts/numina_runtime.py` 作为纯 Python runtime wrapper,负责本地路径、credential redaction、上游状态、dry-run install、setup 和 runner command plan。`scripts/ai4m_lean.py` 继续作为唯一 CLI 总入口,新增 `numina-*` 子命令,并让 `prove/repair/formalize/complete-sorries/batch` 默认走 Numina runtime,`--direct` 保留旧 direct task envelope。文档和 delivery verifier 更新为“官方 Numina runtime assisted workflow”。 +**Architecture:** 新增 `scripts/numina_runtime.py` 作为内部 runtime wrapper,负责本地路径、credential redaction、上游状态、安装/配置计划和官方 runner command plan。公开 CLI 不新增一组平行的 `numina-*` 命令;`doctor` 展示 Numina readiness,`configure --setup-numina` 负责安装/配置,`prove/repair/formalize/complete-sorries/batch` 默认走 Numina runtime,`--direct` 保留旧 direct task envelope。 **Tech Stack:** Python 3 standard library, `unittest`, existing Lean/Lake helper modules, `git`, `uv`, `claude` CLI, official `project-numina/numina-lean-agent`. @@ -12,30 +12,30 @@ ## File Structure -- Create `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: deterministic Numina runtime wrapper, no external API calls in dry-run/doctor/tests. -- Create `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: offline unit tests for paths, credential redaction, install dry-run, dirty upstream, command construction, and direct fallback routing expectations. -- Create `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml`: tracked example config for upstream URL/ref and runtime defaults. -- Create `skills/AI4Math-Lean-Agents/references/numina_runtime.md`: operator reference for official Numina deployment and invocation. -- Modify `skills/AI4Math-Lean-Agents/scripts/common.py`: add `numina-runtime/` to `.ai4math/.gitignore`; keep existing `.env.local` behavior. -- Modify `skills/AI4Math-Lean-Agents/scripts/configure_lean.py`: include Numina readiness summary in `inspect_environment`; add `setup_numina`, `project_name`, and `skip_numina_sync` arguments to `configure`. -- Modify `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: include `uv`, `curl`, and `claude` in tool reporting. -- Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py`: add Numina task-plan builder while preserving direct builder for `--direct`. -- Modify `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: add `numina-*` commands, wire `configure --setup-numina`, add `--direct` to task commands, update exit-code mapping. -- Modify `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py`: require new files and commands; update guidance-first text checks for Numina runtime workflow. +- Create `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: internal deterministic Numina runtime wrapper. It has no external API calls in `doctor`, `dry_run`, or tests. +- Create `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: offline tests for runtime paths, credential redaction, install/configure plans, dirty upstream protection, and runner command construction. +- Create `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml`: tracked example config. +- Create `skills/AI4Math-Lean-Agents/references/numina_runtime.md`: operator reference for official Numina deployment through existing commands. +- Modify `skills/AI4Math-Lean-Agents/scripts/common.py`: add `numina-runtime/` to `.ai4math/.gitignore`. +- Modify `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: include `curl`, `uv`, and `claude` in tool reporting. +- Modify `skills/AI4Math-Lean-Agents/scripts/configure_lean.py`: add Numina readiness to `inspect_environment`; add `setup_numina`, `project_name`, `skip_numina_sync` handling to `configure`. +- Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py`: add default Numina task-plan builder while preserving existing direct builder. +- Modify `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: wire `configure --setup-numina`; add `--direct` to task commands; route task commands through Numina by default. +- Modify `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py`: require new runtime files and update policy checks. - Modify docs: `skills/AI4Math-Lean-Agents/SKILL.md`, `README.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `skills/AI4Math-Lean-Agents/agents/openai.yaml`, `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`. --- -### Task 1: Runtime Paths, Local Env, and Gitignore +### Task 1: Internal Runtime Paths, Credentials, and Gitignore **Files:** - Create: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` - Create: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` - Modify: `skills/AI4Math-Lean-Agents/scripts/common.py` -- [ ] **Step 1: Write failing tests for runtime path defaults and gitignore** +- [ ] **Step 1: Write failing tests** -Add this to `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: +Create `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: ```python from __future__ import annotations @@ -64,9 +64,10 @@ class NuminaRuntimePathTests(unittest.TestCase): with tempfile.TemporaryDirectory() as tmp: paths = runtime_paths(Path(tmp)) - self.assertEqual(paths["root"], str(Path(tmp).resolve() / ".ai4math" / "numina-runtime")) - self.assertEqual(paths["upstream"], str(Path(tmp).resolve() / ".ai4math" / "numina-runtime" / "upstream")) - self.assertEqual(paths["results"], str(Path(tmp).resolve() / ".ai4math" / "numina-runtime" / "results")) + root = Path(tmp).resolve() / ".ai4math" / "numina-runtime" + self.assertEqual(paths["root"], str(root)) + self.assertEqual(paths["upstream"], str(root / "upstream")) + self.assertEqual(paths["results"], str(root / "results")) self.assertEqual(paths["default_upstream_url"], DEFAULT_UPSTREAM_URL) def test_runtime_paths_honor_ai4math_numina_home(self) -> None: @@ -104,12 +105,10 @@ class NuminaRuntimeCredentialTests(unittest.TestCase): self.assertEqual(values["OPENAI_API_KEY"], "sk-test") def test_credential_report_redacts_values(self) -> None: - env = { + report = credential_report({ "ANTHROPIC_AUTH_TOKEN": "secret-token", "OPENAI_API_KEY": "sk-test", - } - - report = credential_report(env) + }) self.assertTrue(report["claude"]["configured"]) self.assertEqual(report["claude"]["variables"]["ANTHROPIC_AUTH_TOKEN"], "") @@ -121,7 +120,7 @@ if __name__ == "__main__": unittest.main() ``` -- [ ] **Step 2: Run the new tests to verify they fail** +- [ ] **Step 2: Verify tests fail** Run: @@ -129,9 +128,9 @@ Run: PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py ``` -Expected: FAIL with `ModuleNotFoundError: No module named 'numina_runtime'` or missing function imports. +Expected: FAIL with missing `numina_runtime` module or missing imported functions. -- [ ] **Step 3: Implement minimal runtime path and credential helpers** +- [ ] **Step 3: Implement runtime path and credential helpers** Create `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: @@ -214,13 +213,13 @@ def credential_report(env: dict[str, str] | None = None) -> dict[str, Any]: } ``` -Modify `ensure_ai4math_gitignore` in `skills/AI4Math-Lean-Agents/scripts/common.py` so the `entries` list includes: +Modify the `entries` list in `skills/AI4Math-Lean-Agents/scripts/common.py`: ```python "numina-runtime/", ``` -- [ ] **Step 4: Run the focused tests to verify they pass** +- [ ] **Step 4: Verify focused tests pass** Run: @@ -230,34 +229,53 @@ PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/te Expected: PASS. -- [ ] **Step 5: Commit Task 1** +- [ ] **Step 5: Commit** ```bash git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py \ skills/AI4Math-Lean-Agents/scripts/common.py -git commit -m "Add Numina runtime path helpers" +git commit -m "Add Numina runtime helpers" ``` --- -### Task 2: Upstream Status, Doctor, and Install Dry-Run +### Task 2: Internal Install, Configure, and Runner Plans **Files:** - Modify: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` - Modify: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` - Modify: `skills/AI4Math-Lean-Agents/scripts/tool_status.py` -- [ ] **Step 1: Add failing tests for upstream status and install planning** +- [ ] **Step 1: Add failing tests for internal plans** Append to `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: ```python -from numina_runtime import build_install_plan, inspect_upstream, numina_doctor # noqa: E402 +from numina_runtime import ( # noqa: E402 + build_batch_plan, + build_configure_plan, + build_install_plan, + build_run_plan, + numina_readiness, +) + + +class NuminaRuntimePlanTests(unittest.TestCase): + def make_lake_project(self, root: Path) -> Path: + (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") + (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") + target = root / "Main.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + return target + def make_upstream(self, root: Path) -> Path: + upstream = root / ".ai4math" / "numina-runtime" / "upstream" + upstream.mkdir(parents=True) + (upstream / ".git").mkdir() + return upstream -class NuminaRuntimeInstallTests(unittest.TestCase): - def test_install_dry_run_clones_official_upstream_when_missing(self) -> None: + def test_install_dry_run_uses_official_upstream(self) -> None: with tempfile.TemporaryDirectory() as tmp: result = build_install_plan(Path(tmp), dry_run=True) @@ -265,32 +283,75 @@ class NuminaRuntimeInstallTests(unittest.TestCase): self.assertEqual(result["status"], "dry_run") self.assertEqual(result["upstream_url"], DEFAULT_UPSTREAM_URL) self.assertEqual(result["actions"][0]["command"][:2], ["git", "clone"]) - self.assertIn(DEFAULT_UPSTREAM_URL, result["actions"][0]["command"]) - def test_dirty_upstream_blocks_update(self) -> None: + def test_dirty_upstream_blocks_non_dry_run_update(self) -> None: with tempfile.TemporaryDirectory() as tmp: - upstream = Path(tmp) / ".ai4math" / "numina-runtime" / "upstream" - upstream.mkdir(parents=True) - (upstream / ".git").mkdir() + upstream = self.make_upstream(Path(tmp)) with patch("numina_runtime.run_command") as run: run.return_value = {"ok": True, "stdout": " M file.py\n", "stderr": "", "returncode": 0} result = build_install_plan(Path(tmp), dry_run=False) + self.assertEqual(str(upstream), result["upstream"]["path"]) self.assertFalse(result["ok"]) self.assertEqual(result["status"], "upstream_dirty") - def test_doctor_reports_missing_upstream_without_installing(self) -> None: + def test_readiness_reports_missing_runtime(self) -> None: with tempfile.TemporaryDirectory() as tmp: - result = numina_doctor(Path(tmp)) + result = numina_readiness(Path(tmp)) self.assertTrue(result["ok"]) - self.assertEqual(result["status"], "reported") - self.assertFalse(result["numina"]["upstream"]["exists"]) - self.assertIn("numina-install", result["recommended_next_action"]) + self.assertFalse(result["upstream"]["exists"]) + self.assertIn("configure --setup-numina", result["recommended_next_action"]) + + def test_configure_plan_includes_install_setup_and_sync(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + self.make_upstream(root) + + result = build_configure_plan(root, project_name="myproofs", skip_sync=False, dry_run=True) + + commands = [action["command"] for action in result["actions"]] + self.assertIn(["git", "fetch", "--all", "--tags"], commands) + self.assertIn(["./setup.sh", "myproofs"], commands) + self.assertIn(["uv", "python", "install"], commands) + self.assertIn(["uv", "sync"], commands) + + def test_run_plan_requires_lake_project(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + target = Path(tmp) / "Main.lean" + target.write_text("example : True := by trivial\n", encoding="utf-8") + + result = build_run_plan(Path(tmp), target, prompt_file=None, prompt="prove it", max_rounds=5, result_dir=None, dry_run=True) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "missing_lake_project") + + def test_run_plan_builds_official_runner_command(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + self.make_upstream(root) + target = self.make_lake_project(root) + prompt = root / "prompt.md" + prompt.write_text("prove the target\n", encoding="utf-8") + + result = build_run_plan(root, target, prompt_file=prompt, prompt=None, max_rounds=7, result_dir=None, dry_run=True) + + self.assertTrue(result["ok"]) + self.assertEqual(result["status"], "dry_run") + self.assertEqual(result["command"][:4], ["python", "-m", "scripts.run_claude", "run"]) + self.assertIn("--max-rounds", result["command"]) + self.assertIn("7", result["command"]) + + def test_batch_plan_requires_existing_target(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = build_batch_plan(Path(tmp), Path(tmp) / "missing", prompt_file=None, max_rounds=5, result_dir=None, dry_run=True) + + self.assertFalse(result["ok"]) + self.assertEqual(result["status"], "file_not_found") ``` -- [ ] **Step 2: Run tests to verify they fail** +- [ ] **Step 2: Verify tests fail** Run: @@ -298,20 +359,18 @@ Run: PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py ``` -Expected: FAIL with missing `build_install_plan`, `inspect_upstream`, or `numina_doctor`. +Expected: FAIL with missing plan functions. -- [ ] **Step 3: Implement upstream inspection and dry-run install planning** +- [ ] **Step 3: Implement internal plan functions** -Add these imports to `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: +Append to `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: ```python +from check_lean_project import find_project_root from common import run_command -from tool_status import find_tool, tool_versions -``` +from tool_status import tool_versions -Add these functions: -```python def upstream_url() -> str: return os.environ.get("NUMINA_LEAN_AGENT_REPO") or DEFAULT_UPSTREAM_URL @@ -320,8 +379,12 @@ def upstream_ref() -> str | None: return os.environ.get("NUMINA_LEAN_AGENT_REF") or None +def _upstream_path(cwd: str | Path) -> Path: + return Path(runtime_paths(cwd)["upstream"]) + + def inspect_upstream(cwd: str | Path) -> dict[str, Any]: - upstream = runtime_root(cwd) / "upstream" + upstream = _upstream_path(cwd) exists = upstream.exists() is_git = (upstream / ".git").exists() result: dict[str, Any] = { @@ -341,49 +404,34 @@ def inspect_upstream(cwd: str | Path) -> dict[str, Any]: return result -def _install_commands(cwd: str | Path) -> list[dict[str, Any]]: - paths = runtime_paths(cwd) - upstream = paths["upstream"] - url = upstream_url() - ref = upstream_ref() - actions: list[dict[str, Any]] = [] - if not Path(upstream).exists(): - actions.append({"command": ["git", "clone", url, upstream], "cwd": str(Path(cwd).resolve())}) - else: - actions.append({"command": ["git", "fetch", "--all", "--tags"], "cwd": upstream}) - if ref: - actions.append({"command": ["git", "checkout", ref], "cwd": upstream}) - return actions - - def build_install_plan(cwd: str | Path, dry_run: bool = False) -> dict[str, Any]: - info = inspect_upstream(cwd) - if info["exists"] and info["is_git"] and info["dirty"] and not dry_run: + upstream = inspect_upstream(cwd) + if upstream["exists"] and upstream["is_git"] and upstream["dirty"] and not dry_run: return { "ok": False, "status": "upstream_dirty", - "upstream": info, - "recommended_next_action": "commit, stash, or clean the upstream checkout before updating", - } - actions = _install_commands(cwd) - if dry_run: - return { - "ok": True, - "status": "dry_run", - "upstream_url": upstream_url(), - "upstream_ref": upstream_ref(), - "actions": actions, + "upstream": upstream, + "recommended_next_action": "clean, commit, or stash .ai4math/numina-runtime/upstream before updating", } + upstream_path = _upstream_path(cwd) + actions: list[dict[str, Any]] = [] + if not upstream_path.exists(): + actions.append({"command": ["git", "clone", upstream_url(), str(upstream_path)], "cwd": str(Path(cwd).resolve())}) + else: + actions.append({"command": ["git", "fetch", "--all", "--tags"], "cwd": str(upstream_path)}) + if upstream_ref(): + actions.append({"command": ["git", "checkout", upstream_ref() or ""], "cwd": str(upstream_path)}) return { "ok": True, - "status": "install_plan_ready", + "status": "dry_run" if dry_run else "install_plan_ready", "upstream_url": upstream_url(), "upstream_ref": upstream_ref(), + "upstream": upstream, "actions": actions, } -def numina_doctor(cwd: str | Path, target: str | Path | None = None) -> dict[str, Any]: +def numina_readiness(cwd: str | Path, target: str | Path | None = None) -> dict[str, Any]: env_local = read_numina_env_local(cwd) upstream = inspect_upstream(cwd) missing = [] @@ -392,165 +440,13 @@ def numina_doctor(cwd: str | Path, target: str | Path | None = None) -> dict[str return { "ok": True, "status": "reported", - "cwd": str(Path(cwd).resolve()), + "runtime_paths": runtime_paths(cwd), "tools": tool_versions(["git", "curl", "uv", "elan", "lean", "lake", "claude", "python3"]), "credentials": credential_report(env_local), - "numina": { - "runtime_paths": runtime_paths(cwd), - "upstream": upstream, - }, + "upstream": upstream, "missing": missing, - "recommended_next_action": "run numina-install --dry-run, then numina-install" if missing else "ready for numina-configure or numina-run", + "recommended_next_action": "run configure --setup-numina --project-name " if missing else "ready for Numina task commands", } -``` - -- [ ] **Step 4: Update tool status defaults** - -Modify `DEFAULT_TOOLS` in `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: - -```python -DEFAULT_TOOLS = ["git", "python3", "curl", "uv", "elan", "lean", "lake", "claude"] -``` - -- [ ] **Step 5: Run focused tests** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py -``` - -Expected: PASS. - -- [ ] **Step 6: Commit Task 2** - -```bash -git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ - skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py \ - skills/AI4Math-Lean-Agents/scripts/tool_status.py -git commit -m "Add Numina runtime doctor and install plan" -``` - ---- - -### Task 3: Numina Configure and Runner Command Plans - -**Files:** -- Modify: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` - -- [ ] **Step 1: Add failing tests for configure/run/from-folder/batch plans** - -Append to `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: - -```python -from numina_runtime import ( # noqa: E402 - build_batch_plan, - build_configure_plan, - build_from_folder_plan, - build_run_plan, -) - - -class NuminaRuntimeCommandPlanTests(unittest.TestCase): - def make_lake_project(self, root: Path) -> Path: - (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") - (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") - source = root / "Main.lean" - source.write_text("example : True := by trivial\n", encoding="utf-8") - return source - - def make_upstream(self, root: Path) -> Path: - upstream = root / ".ai4math" / "numina-runtime" / "upstream" - upstream.mkdir(parents=True) - (upstream / ".git").mkdir() - return upstream - - def test_configure_plan_runs_setup_and_uv_sync(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - self.make_upstream(root) - - result = build_configure_plan(root, project_name="myproofs", skip_sync=False, dry_run=True) - - self.assertTrue(result["ok"]) - commands = [action["command"] for action in result["actions"]] - self.assertIn(["./setup.sh", "myproofs"], commands) - self.assertIn(["uv", "python", "install"], commands) - self.assertIn(["uv", "sync"], commands) - - def test_run_plan_requires_lake_project(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - target = root / "Main.lean" - target.write_text("example : True := by trivial\n", encoding="utf-8") - - result = build_run_plan(root, target, prompt_file=None, prompt="prove it", max_rounds=5, result_dir=None, dry_run=True) - - self.assertFalse(result["ok"]) - self.assertEqual(result["status"], "missing_lake_project") - - def test_run_plan_builds_upstream_runner_command(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - self.make_upstream(root) - target = self.make_lake_project(root) - prompt = root / "prompt.md" - prompt.write_text("prove the target\n", encoding="utf-8") - - result = build_run_plan(root, target, prompt_file=prompt, prompt=None, max_rounds=7, result_dir=None, dry_run=True) - - self.assertTrue(result["ok"]) - self.assertEqual(result["status"], "dry_run") - command = result["command"] - self.assertEqual(command[:4], ["python", "-m", "scripts.run_claude", "run"]) - self.assertIn("--max-rounds", command) - self.assertIn("7", command) - - def test_from_folder_plan_builds_command(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - self.make_upstream(root) - self.make_lake_project(root) - - result = build_from_folder_plan(root, root, prompt_file=None, max_rounds=3, result_dir=None, dry_run=True) - - self.assertTrue(result["ok"]) - self.assertEqual(result["command"][:4], ["python", "-m", "scripts.run_claude", "from-folder"]) - - def test_batch_plan_requires_config(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - result = build_batch_plan(Path(tmp), Path(tmp) / "missing.yaml", dry_run=True) - - self.assertFalse(result["ok"]) - self.assertEqual(result["status"], "file_not_found") -``` - -- [ ] **Step 2: Run tests to verify they fail** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py -``` - -Expected: FAIL with missing plan functions. - -- [ ] **Step 3: Implement configure and runner plan functions** - -Add to `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: - -```python -from check_lean_project import find_project_root - - -def _upstream_path(cwd: str | Path) -> Path: - return Path(runtime_paths(cwd)["upstream"]) - - -def _default_result_dir(cwd: str | Path, task_type: str) -> Path: - root = Path(runtime_paths(cwd)["results"]) - return root / task_type def build_configure_plan( @@ -559,29 +455,27 @@ def build_configure_plan( skip_sync: bool = False, dry_run: bool = False, ) -> dict[str, Any]: + install = build_install_plan(cwd, dry_run=dry_run) + actions = list(install.get("actions", [])) upstream = _upstream_path(cwd) - if not upstream.exists(): - return { - "ok": False, - "status": "missing_numina_runtime", - "recommended_next_action": "run numina-install first", - } - actions = [ - {"command": ["./setup.sh", project_name], "cwd": str(upstream / "tutorial")}, - ] + actions.append({"command": ["./setup.sh", project_name], "cwd": str(upstream / "tutorial")}) if not skip_sync: actions.extend([ {"command": ["uv", "python", "install"], "cwd": str(upstream)}, {"command": ["uv", "sync"], "cwd": str(upstream)}, ]) return { - "ok": True, + "ok": bool(install.get("ok")), "status": "dry_run" if dry_run else "configure_plan_ready", "project_name": project_name, "actions": actions, } +def _default_result_dir(cwd: str | Path, task_type: str) -> Path: + return Path(runtime_paths(cwd)["results"]) / task_type + + def _validate_lake_target(path: Path) -> tuple[Path | None, dict[str, Any] | None]: root = find_project_root(path) if root is None: @@ -606,7 +500,7 @@ def build_run_plan( return error upstream = _upstream_path(cwd) if not upstream.exists(): - return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run numina-install"} + return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run configure --setup-numina --project-name "} if prompt_file is None and not prompt: return {"ok": False, "status": "missing_prompt"} output_dir = Path(result_dir).expanduser().resolve() if result_dir else _default_result_dir(cwd, "run") @@ -626,7 +520,7 @@ def build_run_plan( } -def build_from_folder_plan( +def build_batch_plan( cwd: str | Path, folder: str | Path, prompt_file: str | Path | None, @@ -642,39 +536,30 @@ def build_from_folder_plan( return error upstream = _upstream_path(cwd) if not upstream.exists(): - return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run numina-install"} - output_dir = Path(result_dir).expanduser().resolve() if result_dir else _default_result_dir(cwd, "from-folder") - command = ["python", "-m", "scripts.run_claude", "from-folder", str(folder_path)] + return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run configure --setup-numina --project-name "} + output_dir = Path(result_dir).expanduser().resolve() if result_dir else _default_result_dir(cwd, "batch") + command = ["python", "-m", "scripts.run_claude", "from-folder", str(folder_path), "--max-rounds", str(max_rounds), "--result-dir", str(output_dir)] if prompt_file: command.extend(["--prompt-file", str(Path(prompt_file).expanduser().resolve())]) - command.extend(["--max-rounds", str(max_rounds), "--result-dir", str(output_dir)]) return { "ok": True, - "status": "dry_run" if dry_run else "numina_from_folder_ready", + "status": "dry_run" if dry_run else "numina_batch_ready", "command": command, "cwd": str(upstream), "project_root": str(project_root), "result_dir": str(output_dir), } +``` +- [ ] **Step 4: Update tool status defaults** -def build_batch_plan(cwd: str | Path, config: str | Path, dry_run: bool = False) -> dict[str, Any]: - config_path = Path(config).expanduser().resolve() - if not config_path.exists(): - return {"ok": False, "status": "file_not_found", "config": str(config_path)} - upstream = _upstream_path(cwd) - if not upstream.exists(): - return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run numina-install"} - command = ["python", "-m", "scripts.run_claude", "batch", str(config_path)] - return { - "ok": True, - "status": "dry_run" if dry_run else "numina_batch_ready", - "command": command, - "cwd": str(upstream), - } +Modify `DEFAULT_TOOLS` in `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: + +```python +DEFAULT_TOOLS = ["git", "python3", "curl", "uv", "elan", "lean", "lake", "claude"] ``` -- [ ] **Step 4: Run focused tests** +- [ ] **Step 5: Verify focused tests pass** Run: @@ -684,45 +569,56 @@ PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/te Expected: PASS. -- [ ] **Step 5: Commit Task 3** +- [ ] **Step 6: Commit** ```bash git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ - skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py -git commit -m "Add Numina runtime command planning" + skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py \ + skills/AI4Math-Lean-Agents/scripts/tool_status.py +git commit -m "Add Numina runtime command plans" ``` --- -### Task 4: Wire Numina Commands into `ai4m_lean.py` +### Task 3: Configure and Doctor Use Runtime Readiness **Files:** +- Modify: `skills/AI4Math-Lean-Agents/scripts/configure_lean.py` - Modify: `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py` - Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` -- [ ] **Step 1: Add failing CLI tests for new parser commands** +- [ ] **Step 1: Add failing tests** -Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: +Append to `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py`: ```python - def test_numina_install_dry_run_outputs_official_upstream(self) -> None: + def test_inspect_environment_includes_numina_runtime_summary(self) -> None: with tempfile.TemporaryDirectory() as tmp: - result = subprocess.run( - [sys.executable, str(CLI), "numina-install", "--cwd", tmp, "--dry-run"], - text=True, - capture_output=True, - check=False, - ) + result = inspect_environment(tmp) - self.assertEqual(result.returncode, 0, result.stderr) - payload = json.loads(result.stdout) - self.assertEqual(payload["status"], "dry_run") - self.assertEqual(payload["upstream_url"], "https://github.com/project-numina/numina-lean-agent") + self.assertIn("numina", result) + self.assertFalse(result["numina"]["upstream"]["exists"]) + self.assertIn("configure --setup-numina", result["numina"]["recommended_next_action"]) +``` - def test_numina_doctor_reports_missing_runtime(self) -> None: +Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: + +```python + def test_configure_setup_numina_dry_run_outputs_official_upstream(self) -> None: with tempfile.TemporaryDirectory() as tmp: result = subprocess.run( - [sys.executable, str(CLI), "numina-doctor", "--cwd", tmp], + [ + sys.executable, + str(CLI), + "configure", + "--cwd", + tmp, + "--setup-numina", + "--project-name", + "myproofs", + "--dry-run", + ], text=True, capture_output=True, check=False, @@ -730,149 +626,119 @@ Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: self.assertEqual(result.returncode, 0, result.stderr) payload = json.loads(result.stdout) - self.assertEqual(payload["status"], "reported") - self.assertIn("numina_runtime", payload["missing"]) + self.assertIn("numina_actions", payload) + commands = [action["command"] for action in payload["numina_actions"][0]["actions"]] + self.assertIn(["git", "clone", "https://github.com/project-numina/numina-lean-agent", str(Path(tmp).resolve() / ".ai4math" / "numina-runtime" / "upstream")], commands) ``` -- [ ] **Step 2: Run CLI tests to verify they fail** +- [ ] **Step 2: Verify tests fail** Run: ```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_cli.py +PYTHONDONTWRITEBYTECODE=1 python -m unittest \ + skills/AI4Math-Lean-Agents/tests/test_configure_lean.py \ + skills/AI4Math-Lean-Agents/tests/test_cli.py ``` -Expected: FAIL because `numina-install` and `numina-doctor` are invalid subcommands. +Expected: FAIL because `numina` summary and `--setup-numina` parser args are absent. -- [ ] **Step 3: Add imports and parser entries** +- [ ] **Step 3: Add Numina readiness to environment inspection** -Modify imports in `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: +Modify imports in `skills/AI4Math-Lean-Agents/scripts/configure_lean.py`: ```python -from numina_runtime import ( - build_batch_plan, - build_configure_plan, - build_from_folder_plan, - build_install_plan, - build_run_plan, - numina_doctor, -) +from numina_runtime import build_configure_plan, numina_readiness ``` -Add a helper near `add_common`: +In `inspect_environment`, before the return: ```python -def add_numina_common(parser: argparse.ArgumentParser) -> None: - add_common(parser) - parser.add_argument("--dry-run", action="store_true") + numina = numina_readiness(cwd_path, target=target_path) +``` + +Add to the returned dict: + +```python + "numina": { + "status": numina.get("status"), + "runtime_paths": numina.get("runtime_paths"), + "upstream": numina.get("upstream"), + "missing": numina.get("missing", []), + "recommended_next_action": numina.get("recommended_next_action"), + }, ``` -Add parser definitions in `build_parser()`: +- [ ] **Step 4: Add configure setup arguments** + +Change `configure()` signature in `configure_lean.py`: ```python - numina_doctor_parser = sub.add_parser("numina-doctor", help="Report official Numina runtime readiness") - add_common(numina_doctor_parser) - numina_doctor_parser.add_argument("--target", default=None) - - numina_install = sub.add_parser("numina-install", help="Clone or update official Numina Lean Agent") - add_numina_common(numina_install) - - numina_configure = sub.add_parser("numina-configure", help="Run upstream Numina tutorial setup") - add_numina_common(numina_configure) - numina_configure.add_argument("--project-name", required=True) - numina_configure.add_argument("--skip-sync", action="store_true") - - numina_run = sub.add_parser("numina-run", help="Run official Numina on one Lean file") - add_numina_common(numina_run) - numina_run.add_argument("--file", required=True) - numina_run.add_argument("--prompt-file", default=None) - numina_run.add_argument("--prompt", default=None) - numina_run.add_argument("--max-rounds", type=int, default=5) - numina_run.add_argument("--result-dir", default=None) - - numina_folder = sub.add_parser("numina-from-folder", help="Run official Numina on a folder") - add_numina_common(numina_folder) - numina_folder.add_argument("--folder", required=True) - numina_folder.add_argument("--prompt-file", default=None) - numina_folder.add_argument("--max-rounds", type=int, default=5) - numina_folder.add_argument("--result-dir", default=None) - - numina_batch = sub.add_parser("numina-batch", help="Run official Numina batch config") - add_numina_common(numina_batch) - numina_batch.add_argument("--config-file", "--config", dest="batch_config", required=True) +def configure( + cwd: str | Path = ".", + config_path: str | Path | None = None, + target: str | Path | None = None, + create_workspace: bool = False, + toolchain: str | None = None, + save_local: bool = False, + dry_run: bool = False, + setup_numina: bool = False, + project_name: str | None = None, + skip_numina_sync: bool = False, +) -> dict[str, Any]: ``` -- [ ] **Step 4: Add command dispatch** +Before returning `env`, add: -In `main()`, before existing task dispatch, add: +```python + numina_actions: list[dict[str, Any]] = [] + if setup_numina: + if not project_name: + numina_actions.append({ + "ok": False, + "status": "missing_project_name", + "recommended_next_action": "pass --project-name when using --setup-numina", + }) + else: + numina_actions.append(build_configure_plan(cwd_path, project_name, skip_sync=skip_numina_sync, dry_run=dry_run)) + env["numina_actions"] = numina_actions +``` + +In `ai4m_lean.py`, add parser args to `configure_parser`: ```python - if args.command == "numina-doctor": - result = numina_doctor(args.cwd, target=args.target) - _finish(result, args.json_output) - - if args.command == "numina-install": - result = build_install_plan(args.cwd, dry_run=args.dry_run) - _finish(result, args.json_output) - - if args.command == "numina-configure": - result = build_configure_plan( - args.cwd, - project_name=args.project_name, - skip_sync=args.skip_sync, - dry_run=args.dry_run, - ) - _finish(result, args.json_output) - - if args.command == "numina-run": - result = build_run_plan( - args.cwd, - args.file, - prompt_file=args.prompt_file, - prompt=args.prompt, - max_rounds=args.max_rounds, - result_dir=args.result_dir, - dry_run=args.dry_run, - ) - _finish(result, args.json_output) - - if args.command == "numina-from-folder": - result = build_from_folder_plan( - args.cwd, - args.folder, - prompt_file=args.prompt_file, - max_rounds=args.max_rounds, - result_dir=args.result_dir, - dry_run=args.dry_run, - ) - _finish(result, args.json_output) - - if args.command == "numina-batch": - result = build_batch_plan(args.cwd, args.batch_config, dry_run=args.dry_run) - _finish(result, args.json_output) + configure_parser.add_argument("--setup-numina", action="store_true") + configure_parser.add_argument("--project-name", default=None) + configure_parser.add_argument("--skip-numina-sync", action="store_true") ``` -- [ ] **Step 5: Run CLI tests** +Pass them into `configure()`. + +- [ ] **Step 5: Verify focused tests pass** Run: ```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_cli.py +PYTHONDONTWRITEBYTECODE=1 python -m unittest \ + skills/AI4Math-Lean-Agents/tests/test_configure_lean.py \ + skills/AI4Math-Lean-Agents/tests/test_cli.py ``` Expected: PASS. -- [ ] **Step 6: Commit Task 4** +- [ ] **Step 6: Commit** ```bash -git add skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ +git add skills/AI4Math-Lean-Agents/scripts/configure_lean.py \ + skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ + skills/AI4Math-Lean-Agents/tests/test_configure_lean.py \ skills/AI4Math-Lean-Agents/tests/test_cli.py -git commit -m "Wire Numina runtime CLI commands" +git commit -m "Add Numina setup through configure" ``` --- -### Task 5: Default Task Commands Use Numina, `--direct` Preserves Old Behavior +### Task 4: Default Task Commands Route Through Numina, `--direct` Preserves Old Behavior **Files:** - Modify: `skills/AI4Math-Lean-Agents/scripts/direct_task.py` @@ -880,7 +746,7 @@ git commit -m "Wire Numina runtime CLI commands" - Modify: `skills/AI4Math-Lean-Agents/tests/test_direct_task.py` - Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` -- [ ] **Step 1: Add failing tests for Numina default and direct fallback** +- [ ] **Step 1: Add failing tests** Append to `skills/AI4Math-Lean-Agents/tests/test_direct_task.py`: @@ -889,7 +755,7 @@ from direct_task import build_numina_task # noqa: E402 class NuminaTaskRoutingTests(unittest.TestCase): - def test_numina_task_dry_run_reports_missing_runtime(self) -> None: + def test_numina_task_reports_missing_runtime(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") @@ -946,7 +812,7 @@ Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: self.assertEqual(payload["status"], "missing_numina_runtime") ``` -- [ ] **Step 2: Run tests to verify they fail** +- [ ] **Step 2: Verify tests fail** Run: @@ -960,7 +826,7 @@ Expected: FAIL with missing `build_numina_task` and unknown `--direct`. - [ ] **Step 3: Implement Numina task builder** -Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py`: +Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py` imports: ```python from numina_runtime import build_batch_plan, build_run_plan @@ -979,74 +845,43 @@ def build_numina_task( dry_run: bool = False, ) -> dict[str, Any]: if task_type == "batch": - result = build_batch_plan(cwd, target, dry_run=dry_run) + result = build_batch_plan(cwd, target, prompt_file=prompt_file, max_rounds=max_rounds, result_dir=result_dir, dry_run=dry_run) else: - result = build_run_plan( - cwd, - target, - prompt_file=prompt_file, - prompt=None, - max_rounds=max_rounds, - result_dir=result_dir, - dry_run=dry_run, - ) + result = build_run_plan(cwd, target, prompt_file=prompt_file, prompt=None, max_rounds=max_rounds, result_dir=result_dir, dry_run=dry_run) result.setdefault("task_type", task_type) result["agent_mode"] = "numina-runtime" result["backend"] = "official-numina" return result ``` -- [ ] **Step 4: Wire `--direct` in CLI task commands** +- [ ] **Step 4: Wire `--direct` in task commands** -In `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`, import: +In `ai4m_lean.py`, import: ```python from direct_task import run_direct_task, build_numina_task ``` -Add `--direct` to proof and batch parsers: +Add to proof and batch parser definitions: ```python proof.add_argument("--direct", action="store_true", help="Use direct local Lean task envelope instead of official Numina") ``` -For `batch`: - ```python batch.add_argument("--direct", action="store_true", help="Use direct local Lean batch envelope instead of official Numina") ``` -Change task dispatch: - -```python - if args.command in {"prove", "formalize", "repair", "complete-sorries"}: - if args.direct: - result = run_direct_task(...) - else: - result = build_numina_task( - args.command, - cwd=args.cwd, - target=args.file, - max_rounds=args.max_rounds, - prompt_file=args.prompt_file, - result_dir=args.result_dir, - dry_run=args.dry_run, - ) - ... -``` - -For `batch`, route to `build_numina_task("batch", ...)` unless `args.direct` is set. +In task dispatch, use `run_direct_task` only when `args.direct` is true. Otherwise call `build_numina_task(...)`. -- [ ] **Step 5: Update exit-code mapping for missing Numina runtime** - -Modify `_exit_code` in `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: +Modify `_exit_code`: ```python if status in {"missing_config", "direct_task_missing_config", "missing_numina_runtime", "missing_numina_credentials"}: return EXIT_MISSING_CONFIG ``` -- [ ] **Step 6: Run focused tests** +- [ ] **Step 5: Verify focused tests pass** Run: @@ -1058,7 +893,7 @@ PYTHONDONTWRITEBYTECODE=1 python -m unittest \ Expected: PASS. -- [ ] **Step 7: Commit Task 5** +- [ ] **Step 6: Commit** ```bash git add skills/AI4Math-Lean-Agents/scripts/direct_task.py \ @@ -1070,120 +905,7 @@ git commit -m "Route task commands through Numina runtime" --- -### Task 6: Configure Integration and Environment Readiness - -**Files:** -- Modify: `skills/AI4Math-Lean-Agents/scripts/configure_lean.py` -- Modify: `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py` - -- [ ] **Step 1: Add failing tests for Numina readiness in environment inspection** - -Append to `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py`: - -```python - def test_inspect_environment_includes_numina_runtime_summary(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - result = inspect_environment(tmp) - - self.assertIn("numina", result) - self.assertFalse(result["numina"]["upstream"]["exists"]) - self.assertIn("numina-install", result["numina"]["recommended_next_action"]) -``` - -- [ ] **Step 2: Run tests to verify they fail** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_configure_lean.py -``` - -Expected: FAIL because `numina` key is absent. - -- [ ] **Step 3: Add Numina summary to `inspect_environment`** - -Modify `skills/AI4Math-Lean-Agents/scripts/configure_lean.py` imports: - -```python -from numina_runtime import numina_doctor, build_configure_plan, build_install_plan -``` - -In `inspect_environment`, before return: - -```python - numina = numina_doctor(cwd_path, target=target_path) -``` - -Add to returned dict: - -```python - "numina": { - "status": numina.get("status"), - "upstream": numina.get("numina", {}).get("upstream"), - "runtime_paths": numina.get("numina", {}).get("runtime_paths"), - "missing": numina.get("missing", []), - "recommended_next_action": numina.get("recommended_next_action"), - }, -``` - -- [ ] **Step 4: Add configure `--setup-numina` support** - -Change `configure()` signature: - -```python -def configure(..., setup_numina: bool = False, project_name: str | None = None, skip_numina_sync: bool = False) -> dict[str, Any]: -``` - -Inside `configure`, after workspace handling: - -```python - numina_actions: list[dict[str, Any]] = [] - if setup_numina: - install = build_install_plan(cwd_path, dry_run=dry_run) - numina_actions.append(install) - if install.get("ok") and project_name: - numina_actions.append(build_configure_plan(cwd_path, project_name, skip_sync=skip_numina_sync, dry_run=dry_run)) -``` - -Before return: - -```python - env["numina_actions"] = numina_actions -``` - -In `ai4m_lean.py`, add parser args to `configure`: - -```python - configure_parser.add_argument("--setup-numina", action="store_true") - configure_parser.add_argument("--project-name", default=None) - configure_parser.add_argument("--skip-numina-sync", action="store_true") -``` - -Pass them to `configure()`. - -- [ ] **Step 5: Run configure tests** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_configure_lean.py -``` - -Expected: PASS. - -- [ ] **Step 6: Commit Task 6** - -```bash -git add skills/AI4Math-Lean-Agents/scripts/configure_lean.py \ - skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ - skills/AI4Math-Lean-Agents/tests/test_configure_lean.py -git commit -m "Add Numina runtime configure integration" -``` - ---- - -### Task 7: Config, Reference, and Skill Documentation +### Task 5: Documentation and Delivery Verification **Files:** - Create: `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml` @@ -1192,8 +914,10 @@ git commit -m "Add Numina runtime configure integration" - Modify: `skills/AI4Math-Lean-Agents/agents/openai.yaml` - Modify: `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md` - Modify: `README.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` +- Modify: `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py` +- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` -- [ ] **Step 1: Add runtime example config** +- [ ] **Step 1: Add runtime config and reference** Create `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml`: @@ -1210,35 +934,26 @@ read_env_local = true env_local_path = ".ai4math/numina-runtime/.env.local" ``` -- [ ] **Step 2: Add runtime reference** - Create `skills/AI4Math-Lean-Agents/references/numina_runtime.md`: ```markdown # Numina Runtime Workflow -Use this reference when the user wants official Numina deployment or invocation. +Use this reference when the user wants official Numina deployment or invocation through AI4Math Lean Agents. ## First-Time Setup Run: ```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-doctor --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . --dry-run -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-configure --cwd . --project-name myproofs +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs ``` ## Invocation -Run one file: - -```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-run --cwd . --file path/to/Foo.lean --prompt-file path/to/prompt.md -``` - -Run a task command through the default Numina route: +Run one file through the default Numina route: ```bash python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file path/to/Foo.lean --prompt-file path/to/prompt.md @@ -1252,59 +967,22 @@ python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file pat ## Safety -The Numina route may call external model APIs through upstream Numina and Claude. Never print secret values. Use `.ai4math/numina-runtime/.env.local` or the shell environment for credentials. +The default Numina route may call external model APIs through upstream Numina and Claude. Never print secret values. Use `.ai4math/numina-runtime/.env.local` or the shell environment for credentials. ``` -- [ ] **Step 3: Rewrite `SKILL.md` runtime sections** - -Modify `skills/AI4Math-Lean-Agents/SKILL.md` so the opening says: +- [ ] **Step 2: Update skill and root docs** -```markdown -AI4Math Lean Agents uses an official Numina runtime assisted workflow by default. The skill can fetch `project-numina/numina-lean-agent`, configure local dependencies, call upstream Numina runners, and then use local Lean/Lake guardrails for validation, patch review, `sorry` detection, and minimal failure handoff. -``` +Update: -Replace the old “Numina is not deployed or called” rule with: - -```markdown -Official Numina may be deployed and called when the user requests proof repair, theorem proving, formalization, `sorry` completion, or batch Lean work. Direct local Lean editing remains available as a fallback via `--direct` and for validation/review tasks. -``` +- `skills/AI4Math-Lean-Agents/SKILL.md`: default workflow is official Numina runtime assisted; direct local Lean is fallback via `--direct`; guardrails still validate final delivery. +- `README.md`: show `doctor`, `configure --setup-numina`, default `repair/prove` route, and `--direct`. +- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`: replace no-Numina policy with official Numina runtime default plus external API warning. +- `skills/AI4Math-Lean-Agents/agents/openai.yaml`: mention official Numina runtime. +- `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`: add a top note that it is historical background and no longer defines a no-call policy. -Add `references/numina_runtime.md` to the References list. +- [ ] **Step 3: Update delivery verifier** -- [ ] **Step 4: Update root-facing docs** - -Update these files consistently: - -- `README.md`: describe default Numina runtime, new `numina-*` commands, external API caveat. -- `AGENTS.md`: instruct agents to use `AI4Math-Lean-Agents/SKILL.md`, deploy/call official Numina by default, and keep direct guardrails. -- `CLAUDE.md`: same as AGENTS, with Claude CLI credential note. -- `GEMINI.md`: same policy wording for Gemini. -- `skills/AI4Math-Lean-Agents/agents/openai.yaml`: update `short_description` and `default_prompt` to mention official Numina runtime. -- `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`: add a top note saying it is historical background and no longer defines the no-call policy. - -- [ ] **Step 5: Commit Task 7** - -```bash -git add README.md AGENTS.md CLAUDE.md GEMINI.md \ - skills/AI4Math-Lean-Agents/SKILL.md \ - skills/AI4Math-Lean-Agents/agents/openai.yaml \ - skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml \ - skills/AI4Math-Lean-Agents/references/numina_runtime.md \ - skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md -git commit -m "Update skill docs for official Numina runtime" -``` - ---- - -### Task 8: Delivery Verification and Full Test Pass - -**Files:** -- Modify: `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` - -- [ ] **Step 1: Update required delivery files and commands** - -Modify `REQUIRED_FILES` in `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py` to include: +Modify `REQUIRED_FILES` in `verify_delivery.py`: ```python "config/numina_runtime.example.toml", @@ -1312,20 +990,9 @@ Modify `REQUIRED_FILES` in `skills/AI4Math-Lean-Agents/scripts/verify_delivery.p "scripts/numina_runtime.py", ``` -Modify `REQUIRED_COMMANDS` to include: - -```python - "numina-doctor", - "numina-install", - "numina-configure", - "numina-run", - "numina-from-folder", - "numina-batch", -``` - -- [ ] **Step 2: Update guidance check** +Do not add public `numina-*` commands to `REQUIRED_COMMANDS`. The required command set remains centered on existing `doctor`, `configure`, and task commands. -Replace `_guidance_first_check()` required phrases with phrases matching the new policy: +Replace `_guidance_first_check()` required phrases with: ```python required_phrases = [ @@ -1336,22 +1003,20 @@ Replace `_guidance_first_check()` required phrases with phrases matching the new ] ``` -Update `external_api_note` in `verify()`: +Update `external_api_note`: ```python "external_api_note": "The default Numina runtime workflow may call upstream Numina, Claude, and external model APIs. Guardrail commands and default tests remain local/offline.", ``` -- [ ] **Step 3: Add CLI delivery expectation** - -In `skills/AI4Math-Lean-Agents/tests/test_cli.py`, update `test_verify_delivery_package_checks`: +Update `test_verify_delivery_package_checks` in `test_cli.py`: ```python - self.assertIn("numina-install", payload["commands"]["available"]) self.assertIn("scripts/numina_runtime.py", [item["path"] for item in payload["files"]]) + self.assertIn("configure", payload["commands"]["available"]) ``` -- [ ] **Step 4: Run package tests** +- [ ] **Step 4: Run full tests and delivery verification** Run: @@ -1361,8 +1026,6 @@ PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/AI4Math-Lean-Age Expected: all tests pass. -- [ ] **Step 5: Run delivery verification** - Run: ```bash @@ -1371,12 +1034,18 @@ PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py Expected: JSON has `"ok": true`, `"status": "delivery_ready"`, and `"unit_tests": {"ok": true, ...}`. -- [ ] **Step 6: Commit Task 8** +- [ ] **Step 5: Commit** ```bash -git add skills/AI4Math-Lean-Agents/scripts/verify_delivery.py \ +git add README.md AGENTS.md CLAUDE.md GEMINI.md \ + skills/AI4Math-Lean-Agents/SKILL.md \ + skills/AI4Math-Lean-Agents/agents/openai.yaml \ + skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml \ + skills/AI4Math-Lean-Agents/references/numina_runtime.md \ + skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md \ + skills/AI4Math-Lean-Agents/scripts/verify_delivery.py \ skills/AI4Math-Lean-Agents/tests/test_cli.py -git commit -m "Verify Numina runtime delivery" +git commit -m "Document official Numina runtime workflow" ``` --- @@ -1402,18 +1071,18 @@ Expected: `"ok": true` and `"status": "delivery_ready"`. - [ ] Run: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . --dry-run +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name dryrun --dry-run ``` -Expected: JSON includes `"status": "dry_run"` and `"upstream_url": "https://github.com/project-numina/numina-lean-agent"`. +Expected: JSON includes `numina_actions` and the official upstream URL. - [ ] Run: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-doctor --cwd . +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . ``` -Expected: JSON includes `numina.runtime_paths`, `credentials`, and no secret values. +Expected: JSON includes a Numina readiness summary and no secret values. - [ ] Run: @@ -1427,6 +1096,6 @@ Expected: no unstaged or uncommitted implementation changes. ## Self-Review Notes -- Spec coverage: The plan covers existing-skill modification, official upstream install/dry-run, runtime state, CLI commands, task routing, `--direct`, docs, tests, delivery verifier, and external API disclosure. +- Spec coverage: The plan covers existing-skill modification, official upstream install/configure through existing CLI, runtime state, task routing, `--direct`, docs, tests, delivery verifier, and external API disclosure. - Completeness scan: The plan uses concrete code snippets, exact commands, expected outputs, and no open-ended steps. - Type consistency: Runtime status names use the spec vocabulary: `missing_numina_runtime`, `upstream_dirty`, `numina_run_ready`, and `direct_task_ready`. diff --git a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md index d04f84f..41b17cd 100644 --- a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md +++ b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md @@ -101,18 +101,16 @@ https://github.com/project-numina/numina-lean-agent ## CLI 设计 -继续用 `scripts/ai4m_lean.py` 作为总入口,在现有命令旁新增 Numina runtime 命令。 +继续用 `scripts/ai4m_lean.py` 作为总入口,但不增加一组平行的 `numina-*` 公开命令。Numina 部署和调用应该折叠进现有命令: ```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-doctor --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-install --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-configure --cwd . --project-name myproofs -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-run --cwd . --file /path/to/Foo.lean --prompt-file /path/to/prompt.md -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-from-folder --cwd . --folder /path/to/LeanFolder -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py numina-batch --cwd . --config /path/to/config.yaml +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file /path/to/Foo.lean --prompt-file /path/to/prompt.md +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file /path/to/Foo.lean --direct --dry-run ``` -底层实现放在 `scripts/numina_runtime.py`,`ai4m_lean.py` 只负责参数解析、调用和统一 exit code。 +底层实现放在 `scripts/numina_runtime.py`,但这些函数是内部实现细节。`ai4m_lean.py` 只公开少量现有入口:`doctor` 展示 Numina readiness,`configure --setup-numina` 执行安装/配置,证明修复类任务默认调用官方 Numina,`--direct` 保留旧 direct task envelope。 ## 现有命令语义调整 @@ -142,8 +140,9 @@ python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name mypr 它等价于执行: -1. `numina-install` -2. `numina-configure --project-name myproofs` +1. 内部 Numina upstream install/update; +2. 内部 Numina setup/configure; +3. 可选 dependency sync,默认开启,可用 `--skip-numina-sync` 跳过。 ### 改造任务命令 @@ -170,11 +169,11 @@ python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name mypr ## Numina Runtime Wrapper -`scripts/numina_runtime.py` 需要提供可单测的纯函数和命令入口。 +`scripts/numina_runtime.py` 需要提供可单测的纯函数。第一版不把这些函数全部暴露成公开 CLI 子命令。 -### `numina-doctor` +### readiness/doctor helpers -输出 JSON,包含: +供 `doctor` 和 `env` 调用,输出 JSON 片段,包含: - `git`、`curl`、`uv`、`elan`、`lean`、`lake`、`claude`、`python` 可用性; - 上游是否已 clone、当前 commit、是否 dirty; @@ -188,9 +187,9 @@ credential 诊断区分: - Numina skill keys:`GEMINI_API_KEY`、`OPENAI_API_KEY`、`LEAN_LEANDEX_API_KEY`、`AXLE_API_KEY`; - required 和 optional keys。 -`numina-doctor` 不得调用外部模型 API。 +readiness/doctor helpers 不得调用外部模型 API。 -### `numina-install` +### install helpers clone 或更新官方 Numina: @@ -202,17 +201,17 @@ clone 或更新官方 Numina: 第一版必须支持: ```bash -python scripts/ai4m_lean.py numina-install --cwd . --dry-run +python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run ``` -`--dry-run` 返回将执行的 clone/fetch/checkout 命令,不实际执行。 +`--dry-run` 返回将执行的 clone/fetch/checkout/setup/sync 命令,不实际执行。 -### `numina-configure` +### configure helpers 为指定 project name 运行上游 setup: ```bash -python scripts/ai4m_lean.py numina-configure --cwd . --project-name myproofs +python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs ``` 行为: @@ -224,12 +223,12 @@ python scripts/ai4m_lean.py numina-configure --cwd . --project-name myproofs - 记录本地 metadata; - 失败时返回 `setup_failed` 和具体 stderr/stdout 摘要。 -### `numina-run` +### run helpers -单文件调用官方 runner: +供现有 `prove`、`formalize`、`repair` 和 `complete-sorries` 调用官方 runner: ```bash -python scripts/ai4m_lean.py numina-run \ +python scripts/ai4m_lean.py repair \ --cwd . \ --file /path/to/Foo.lean \ --prompt-file /path/to/prompt.md \ @@ -249,33 +248,23 @@ python scripts/ai4m_lean.py numina-run \ python -m scripts.run_claude run --prompt-file --max-rounds --result-dir ``` -### `numina-from-folder` +### folder/batch helpers -文件夹模式调用: +供现有 `batch` 或未来 folder 任务调用: ```bash -python scripts/ai4m_lean.py numina-from-folder --cwd . --folder /path/to/LeanFolder +python scripts/ai4m_lean.py batch --cwd . --folder /path/to/LeanFolder ``` 默认 result dir 放在 `.ai4math/numina-runtime/results/`。 -### `numina-batch` - -批量配置调用: - -```bash -python scripts/ai4m_lean.py numina-batch --cwd . --config /path/to/config.yaml -``` - -wrapper 先验证 config 存在,再调用上游 batch。 - ## Skill 文档改造 `SKILL.md` 需要从“Numina 不部署不调用”改成: - 默认工作流是官方 Numina runtime assisted workflow; - Codex 先用本地 guardrails 识别目标、检查 Lake 项目、检查 runtime; -- runtime 未安装时,引导 `numina-install` 和 `numina-configure`; +- runtime 未安装时,引导 `configure --setup-numina --project-name ...`; - runtime ready 时调用官方 Numina runner; - runner 结束后用 `check`、`detect-sorry`、`review` 做交付前验证; - 如果 Numina 路线失败,使用 `minimize-failure` 给出最小失败片段和下一步。 @@ -318,10 +307,10 @@ wrapper 必须读取 `.ai4math/numina-runtime/.env.local`(如果存在), - Numina runtime 默认路径解析; - `.ai4math/.gitignore` 写入 `numina-runtime/`; - Lake project root detection 复用现有逻辑; -- `numina-install --dry-run` 使用官方上游 URL; +- `configure --setup-numina --dry-run` 使用官方上游 URL; - dirty upstream 保护; - credential redaction; -- `numina-run`、`numina-from-folder`、`numina-batch` 命令构造; +- `prove/repair/complete-sorries/batch --dry-run` 构造官方 Numina runner command plan; - `prove/repair/complete-sorries/batch --dry-run` 走 Numina command plan; - `--direct` 保留旧 direct task envelope; - `verify-delivery` 检查新增文件和命令。 @@ -345,8 +334,8 @@ AI4MATH_NUMINA_INTEGRATION=1 - `verify-delivery --run-tests` 通过; - 新增 Numina runtime offline tests 通过; -- `numina-install --dry-run` 输出官方上游 URL; -- `numina-doctor` 在未安装 runtime 的 fresh checkout 上清楚报告下一步; +- `configure --setup-numina --dry-run` 输出官方上游 URL; +- `doctor` 在未安装 runtime 的 fresh checkout 上清楚报告下一步; - `SKILL.md`、README、AGENTS/CLAUDE/GEMINI 说明一致:本 skill 现在会部署并调用官方 Numina; - 最终交付仍拒绝 `sorry`、`admit` 和新 `axiom`。 From 6782580ef19054e6abfdcb7edfdc326b621ec90e Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 21:44:41 +0800 Subject: [PATCH 08/37] Make Numina workflow agentic --- .../2026-05-24-ai4math-numina-runtime.md | 196 ++---------------- ...-05-24-numina-lean-agent-runtime-design.md | 48 ++--- 2 files changed, 32 insertions(+), 212 deletions(-) diff --git a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md index 3fedec0..f3e8fff 100644 --- a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md +++ b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md @@ -2,9 +2,9 @@ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** 改造现有 `AI4Math-Lean-Agents` skill,使其通过现有 CLI 自动部署并调用官方 `project-numina/numina-lean-agent`,同时保留现有 Lean guardrails 和 `--direct` fallback。 +**Goal:** 改造现有 `AI4Math-Lean-Agents` skill,使 coding agent 能通过交互式流程部署并调用官方 `project-numina/numina-lean-agent`,同时保留现有 Lean guardrails 和 direct task envelope。 -**Architecture:** 新增 `scripts/numina_runtime.py` 作为内部 runtime wrapper,负责本地路径、credential redaction、上游状态、安装/配置计划和官方 runner command plan。公开 CLI 不新增一组平行的 `numina-*` 命令;`doctor` 展示 Numina readiness,`configure --setup-numina` 负责安装/配置,`prove/repair/formalize/complete-sorries/batch` 默认走 Numina runtime,`--direct` 保留旧 direct task envelope。 +**Architecture:** 新增 `scripts/numina_runtime.py` 作为内部 runtime helper,负责本地路径、credential redaction、上游状态、安装/配置计划和官方 runner command plan。公开 CLI 不新增一组平行的 `numina-*` 命令;`doctor` 展示 Numina readiness,`configure --setup-numina` 负责可审阅的安装/配置,`SKILL.md` 和 `references/numina_runtime.md` 指导 coding agent 何时向用户说明、何时调用上游 Numina、何时使用本地 guardrails。现有 `prove/repair/formalize/complete-sorries/batch` 保持 task envelope/辅助入口,不强制改造成 Numina 流水线。 **Tech Stack:** Python 3 standard library, `unittest`, existing Lean/Lake helper modules, `git`, `uv`, `claude` CLI, official `project-numina/numina-lean-agent`. @@ -19,8 +19,7 @@ - Modify `skills/AI4Math-Lean-Agents/scripts/common.py`: add `numina-runtime/` to `.ai4math/.gitignore`. - Modify `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: include `curl`, `uv`, and `claude` in tool reporting. - Modify `skills/AI4Math-Lean-Agents/scripts/configure_lean.py`: add Numina readiness to `inspect_environment`; add `setup_numina`, `project_name`, `skip_numina_sync` handling to `configure`. -- Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py`: add default Numina task-plan builder while preserving existing direct builder. -- Modify `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: wire `configure --setup-numina`; add `--direct` to task commands; route task commands through Numina by default. +- Modify `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: wire `configure --setup-numina`; keep task commands as existing envelopes. - Modify `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py`: require new runtime files and update policy checks. - Modify docs: `skills/AI4Math-Lean-Agents/SKILL.md`, `README.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `skills/AI4Math-Lean-Agents/agents/openai.yaml`, `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`. @@ -738,174 +737,7 @@ git commit -m "Add Numina setup through configure" --- -### Task 4: Default Task Commands Route Through Numina, `--direct` Preserves Old Behavior - -**Files:** -- Modify: `skills/AI4Math-Lean-Agents/scripts/direct_task.py` -- Modify: `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_direct_task.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` - -- [ ] **Step 1: Add failing tests** - -Append to `skills/AI4Math-Lean-Agents/tests/test_direct_task.py`: - -```python -from direct_task import build_numina_task # noqa: E402 - - -class NuminaTaskRoutingTests(unittest.TestCase): - def test_numina_task_reports_missing_runtime(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") - (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") - target = root / "Main.lean" - target.write_text("example : True := by trivial\n", encoding="utf-8") - - result = build_numina_task("repair", root, target, max_rounds=5, prompt_file=None, result_dir=None, dry_run=True) - - self.assertFalse(result["ok"]) - self.assertEqual(result["status"], "missing_numina_runtime") - self.assertEqual(result["backend"], "official-numina") -``` - -Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: - -```python - def test_repair_direct_preserves_old_task_envelope(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") - (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") - target = root / "Main.lean" - target.write_text("example : True := by trivial\n", encoding="utf-8") - result = subprocess.run( - [sys.executable, str(CLI), "repair", "--cwd", str(root), "--file", str(target), "--dry-run", "--direct"], - text=True, - capture_output=True, - check=False, - ) - - self.assertEqual(result.returncode, 0, result.stderr) - payload = json.loads(result.stdout) - self.assertEqual(payload["agent_mode"], "direct-coding-agent") - self.assertEqual(payload["backend"], "none") - - def test_repair_default_routes_to_numina(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") - (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") - target = root / "Main.lean" - target.write_text("example : True := by trivial\n", encoding="utf-8") - result = subprocess.run( - [sys.executable, str(CLI), "repair", "--cwd", str(root), "--file", str(target), "--dry-run"], - text=True, - capture_output=True, - check=False, - ) - - self.assertEqual(result.returncode, 4, result.stderr) - payload = json.loads(result.stdout) - self.assertEqual(payload["backend"], "official-numina") - self.assertEqual(payload["status"], "missing_numina_runtime") -``` - -- [ ] **Step 2: Verify tests fail** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest \ - skills/AI4Math-Lean-Agents/tests/test_direct_task.py \ - skills/AI4Math-Lean-Agents/tests/test_cli.py -``` - -Expected: FAIL with missing `build_numina_task` and unknown `--direct`. - -- [ ] **Step 3: Implement Numina task builder** - -Modify `skills/AI4Math-Lean-Agents/scripts/direct_task.py` imports: - -```python -from numina_runtime import build_batch_plan, build_run_plan -``` - -Add: - -```python -def build_numina_task( - task_type: str, - cwd: str | Path, - target: str | Path, - max_rounds: int = 5, - prompt_file: str | Path | None = None, - result_dir: str | Path | None = None, - dry_run: bool = False, -) -> dict[str, Any]: - if task_type == "batch": - result = build_batch_plan(cwd, target, prompt_file=prompt_file, max_rounds=max_rounds, result_dir=result_dir, dry_run=dry_run) - else: - result = build_run_plan(cwd, target, prompt_file=prompt_file, prompt=None, max_rounds=max_rounds, result_dir=result_dir, dry_run=dry_run) - result.setdefault("task_type", task_type) - result["agent_mode"] = "numina-runtime" - result["backend"] = "official-numina" - return result -``` - -- [ ] **Step 4: Wire `--direct` in task commands** - -In `ai4m_lean.py`, import: - -```python -from direct_task import run_direct_task, build_numina_task -``` - -Add to proof and batch parser definitions: - -```python - proof.add_argument("--direct", action="store_true", help="Use direct local Lean task envelope instead of official Numina") -``` - -```python - batch.add_argument("--direct", action="store_true", help="Use direct local Lean batch envelope instead of official Numina") -``` - -In task dispatch, use `run_direct_task` only when `args.direct` is true. Otherwise call `build_numina_task(...)`. - -Modify `_exit_code`: - -```python - if status in {"missing_config", "direct_task_missing_config", "missing_numina_runtime", "missing_numina_credentials"}: - return EXIT_MISSING_CONFIG -``` - -- [ ] **Step 5: Verify focused tests pass** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest \ - skills/AI4Math-Lean-Agents/tests/test_direct_task.py \ - skills/AI4Math-Lean-Agents/tests/test_cli.py -``` - -Expected: PASS. - -- [ ] **Step 6: Commit** - -```bash -git add skills/AI4Math-Lean-Agents/scripts/direct_task.py \ - skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ - skills/AI4Math-Lean-Agents/tests/test_direct_task.py \ - skills/AI4Math-Lean-Agents/tests/test_cli.py -git commit -m "Route task commands through Numina runtime" -``` - ---- - -### Task 5: Documentation and Delivery Verification +### Task 4: Documentation and Delivery Verification **Files:** - Create: `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml` @@ -953,29 +785,29 @@ python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup ## Invocation -Run one file through the default Numina route: +After explaining the external API implications and confirming with the user, the coding agent can run an upstream Numina command from the cloned upstream checkout. A typical command shape is: ```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file path/to/Foo.lean --prompt-file path/to/prompt.md +python -m scripts.run_claude run path/to/Foo.lean --prompt-file path/to/prompt.md --max-rounds 5 --result-dir .ai4math/numina-runtime/results/run ``` -Use the old direct local task envelope only when explicitly requested: +The existing direct local task envelope remains available: ```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file path/to/Foo.lean --direct --dry-run +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file path/to/Foo.lean --dry-run ``` ## Safety -The default Numina route may call external model APIs through upstream Numina and Claude. Never print secret values. Use `.ai4math/numina-runtime/.env.local` or the shell environment for credentials. +The Numina route may call external model APIs through upstream Numina and Claude. Never print secret values. Use `.ai4math/numina-runtime/.env.local` or the shell environment for credentials. ``` - [ ] **Step 2: Update skill and root docs** Update: -- `skills/AI4Math-Lean-Agents/SKILL.md`: default workflow is official Numina runtime assisted; direct local Lean is fallback via `--direct`; guardrails still validate final delivery. -- `README.md`: show `doctor`, `configure --setup-numina`, default `repair/prove` route, and `--direct`. +- `skills/AI4Math-Lean-Agents/SKILL.md`: workflow is official Numina runtime assisted and human-in-the-loop; direct local Lean guardrails remain part of diagnosis and final validation. +- `README.md`: show `doctor`, `configure --setup-numina`, an example upstream `scripts.run_claude` command, and existing `repair/prove --dry-run` task-envelope usage. - `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`: replace no-Numina policy with official Numina runtime default plus external API warning. - `skills/AI4Math-Lean-Agents/agents/openai.yaml`: mention official Numina runtime. - `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`: add a top note that it is historical background and no longer defines a no-call policy. @@ -999,14 +831,14 @@ Replace `_guidance_first_check()` required phrases with: "## Agent Playbook", "## Helper Toolbox", "official Numina runtime", - "Direct local Lean editing remains available as a fallback via `--direct`", + "Use official Numina through a human-in-the-loop runtime workflow", ] ``` Update `external_api_note`: ```python - "external_api_note": "The default Numina runtime workflow may call upstream Numina, Claude, and external model APIs. Guardrail commands and default tests remain local/offline.", + "external_api_note": "The Numina runtime workflow may call upstream Numina, Claude, and external model APIs after user-facing explanation/confirmation. Guardrail commands and default tests remain local/offline.", ``` Update `test_verify_delivery_package_checks` in `test_cli.py`: @@ -1096,6 +928,6 @@ Expected: no unstaged or uncommitted implementation changes. ## Self-Review Notes -- Spec coverage: The plan covers existing-skill modification, official upstream install/configure through existing CLI, runtime state, task routing, `--direct`, docs, tests, delivery verifier, and external API disclosure. +- Spec coverage: The plan covers existing-skill modification, official upstream install/configure through existing CLI, runtime state, human-in-the-loop Numina invocation guidance, docs, tests, delivery verifier, and external API disclosure. - Completeness scan: The plan uses concrete code snippets, exact commands, expected outputs, and no open-ended steps. - Type consistency: Runtime status names use the spec vocabulary: `missing_numina_runtime`, `upstream_dirty`, `numina_run_ready`, and `direct_task_ready`. diff --git a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md index 41b17cd..9db44ca 100644 --- a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md +++ b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md @@ -106,11 +106,10 @@ https://github.com/project-numina/numina-lean-agent ```bash python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file /path/to/Foo.lean --prompt-file /path/to/prompt.md -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file /path/to/Foo.lean --direct --dry-run +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file /path/to/Foo.lean --dry-run ``` -底层实现放在 `scripts/numina_runtime.py`,但这些函数是内部实现细节。`ai4m_lean.py` 只公开少量现有入口:`doctor` 展示 Numina readiness,`configure --setup-numina` 执行安装/配置,证明修复类任务默认调用官方 Numina,`--direct` 保留旧 direct task envelope。 +底层实现放在 `scripts/numina_runtime.py`,但这些函数是内部实现细节。`ai4m_lean.py` 只公开少量现有入口:`doctor` 展示 Numina readiness,`configure --setup-numina` 执行安装/配置,证明修复类任务继续可作为 task envelope 或 dry-run 辅助。是否调用官方 Numina,应由 coding agent 根据 `SKILL.md`、用户确认和当前项目状态决定。 ## 现有命令语义调整 @@ -144,28 +143,17 @@ python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name mypr 2. 内部 Numina setup/configure; 3. 可选 dependency sync,默认开启,可用 `--skip-numina-sync` 跳过。 -### 改造任务命令 +### 任务调用的交互原则 -这些任务命令应默认进入 Numina runtime 路线: +不要把 `prove`、`formalize`、`repair`、`complete-sorries`、`batch` 改成闭合的 Numina CLI 流水线。这个 skill 的主体验应该是人机交互: -- `prove` -- `formalize` -- `repair` -- `complete-sorries` -- `batch` +1. coding agent 先读用户目标、Lean 项目、当前错误和本地 runtime 状态; +2. 如果需要部署或调用官方 Numina,先说明会 clone 上游、配置依赖、可能调用外部模型 API; +3. 用户同意后,coding agent 可调用 `configure --setup-numina` 或直接运行上游 `scripts.run_claude`; +4. 如果 runtime 缺失、credential 缺失或目标不在 Lake 项目内,coding agent 给出解释和下一步,而不是静默 fallback; +5. Numina runner 结束后,coding agent 再用本地 `check`、`detect-sorry`、`review`、`minimize-failure` 做交付判断。 -默认行为: - -1. 检查 target 或 folder 是否存在。 -2. 检查 target 是否在 Lake 项目内。 -3. 检查 Numina runtime 是否已安装、依赖是否准备好、credential 是否足够。 -4. 如果缺 runtime,返回 `missing_numina_runtime` 和下一步命令,不静默 fallback。 -5. 如果 runtime ready,则构造并执行官方 Numina runner 命令。 - -为保留现有轻量能力,第一版允许 `--direct` 或 `--dry-run`: - -- `--dry-run`:只返回 Numina command plan,不执行。 -- `--direct`:沿用现有 direct coding-agent task envelope,用于用户明确要求不调用 Numina 的场景。 +现有任务命令可以继续作为 task envelope、dry-run 说明或辅助入口,但第一版不要求它们自动执行 Numina。关键能力应写在 `SKILL.md` 和 `references/numina_runtime.md`,让 coding agent 在上下文中自行决定。 ## Numina Runtime Wrapper @@ -225,7 +213,7 @@ python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name mypr ### run helpers -供现有 `prove`、`formalize`、`repair` 和 `complete-sorries` 调用官方 runner: +供 coding agent 在交互确认后调用官方 runner: ```bash python scripts/ai4m_lean.py repair \ @@ -250,7 +238,7 @@ python -m scripts.run_claude run --prompt-file --max-rounds ### folder/batch helpers -供现有 `batch` 或未来 folder 任务调用: +供 coding agent 在交互确认后调用 folder/batch 类官方 runner: ```bash python scripts/ai4m_lean.py batch --cwd . --folder /path/to/LeanFolder @@ -310,9 +298,9 @@ wrapper 必须读取 `.ai4math/numina-runtime/.env.local`(如果存在), - `configure --setup-numina --dry-run` 使用官方上游 URL; - dirty upstream 保护; - credential redaction; -- `prove/repair/complete-sorries/batch --dry-run` 构造官方 Numina runner command plan; -- `prove/repair/complete-sorries/batch --dry-run` 走 Numina command plan; -- `--direct` 保留旧 direct task envelope; +- `configure --setup-numina --dry-run` 构造官方 Numina install/setup command plan; +- task commands 继续保留旧 direct task envelope,不被强制改造成 Numina 流水线; +- `SKILL.md` 明确列出 coding agent 何时应调用 Numina、何时应停下来问用户。 - `verify-delivery` 检查新增文件和命令。 默认测试不得: @@ -342,7 +330,7 @@ AI4MATH_NUMINA_INTEGRATION=1 ## 实现决策 - 不新增 sister skill,直接改造 `AI4Math-Lean-Agents`。 -- 保留现有 direct Lean guardrails。 -- 证明/修复类任务默认准备或调用 Numina runtime。 -- 第一版必须支持 `--dry-run` 和 `--direct`,降低迁移风险。 +- 保留现有 direct Lean guardrails 和任务 envelope。 +- Numina 部署和调用作为 skill 的交互式主能力,不做成大量公开 CLI。 +- 第一版必须支持 `configure --setup-numina --dry-run`,降低真实部署风险。 - 默认 runtime 根目录是 `.ai4math/numina-runtime/`。 From bf3a72e9008f8383bdf3a9a26dc073632a86c29d Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 21:59:55 +0800 Subject: [PATCH 09/37] Make Lean skill Numina runtime ready --- AGENTS.md | 5 +- CLAUDE.md | 4 +- GEMINI.md | 2 +- README.md | 8 +- .../2026-05-24-ai4math-numina-runtime.md | 19 +- ...-05-24-numina-lean-agent-runtime-design.md | 4 +- skills/AI4Math-Lean-Agents/SKILL.md | 32 +- skills/AI4Math-Lean-Agents/agents/openai.yaml | 4 +- skills/AI4Math-Lean-Agents/config/env.example | 1 + .../config/numina_runtime.example.toml | 12 + .../references/lean_runtime_configuration.md | 6 +- .../references/numina_reverse_analysis.md | 12 +- .../references/numina_runtime.md | 31 ++ .../schemas/config.schema.json | 3 +- .../AI4Math-Lean-Agents/scripts/ai4m_lean.py | 6 + skills/AI4Math-Lean-Agents/scripts/common.py | 1 + .../scripts/configure_lean.py | 22 + .../scripts/numina_runtime.py | 414 ++++++++++++++++++ .../scripts/tool_status.py | 2 +- .../scripts/verify_delivery.py | 8 +- skills/AI4Math-Lean-Agents/tests/test_cli.py | 28 ++ .../tests/test_configure_lean.py | 10 + .../tests/test_numina_runtime.py | 150 +++++++ 23 files changed, 740 insertions(+), 44 deletions(-) create mode 100644 skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml create mode 100644 skills/AI4Math-Lean-Agents/references/numina_runtime.md create mode 100644 skills/AI4Math-Lean-Agents/scripts/numina_runtime.py create mode 100644 skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py diff --git a/AGENTS.md b/AGENTS.md index a3a2b1f..232f78e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,14 +1,15 @@ # Agent Instructions -Use the canonical skill at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, and minimal failure handoff. +Use the canonical skill at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, optional official Numina runtime deployment/calls, and minimal failure handoff. Core rules: - The coding agent directly operates Lean; do not treat helper CLI commands as a proof backend. -- Do not deploy or call Numina, Claude Code CLI, or external model APIs for this skill. +- Numina is optional: deploy or call the official runtime only through the human-in-the-loop flow in `references/numina_runtime.md`. - Prefer the user's existing Lake project. Use `.ai4math/lean-workspace` only when a standalone file needs project context. - Preserve theorem statements unless the user explicitly approves a change. - Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. +- Do not commit API keys, local runtime state, or machine-specific Numina paths. Useful validation: diff --git a/CLAUDE.md b/CLAUDE.md index ce951ef..8a3cd67 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,6 @@ For Lean work in this repository, read and follow: skills/AI4Math-Lean-Agents/SKILL.md ``` -Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run Lean/Lake checks frequently, and use the helper CLI only for deterministic checks such as environment inspection, patch review, `sorry` detection, and minimal failure extraction. +Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run Lean/Lake checks frequently, and use the helper CLI only for deterministic checks such as environment inspection, optional Numina readiness/setup, patch review, `sorry` detection, and minimal failure extraction. -Do not deploy Numina or require API keys for this workflow. +Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index af612dc..637cda0 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -8,4 +8,4 @@ skills/AI4Math-Lean-Agents/SKILL.md The agent should directly inspect and edit Lean files, validate with Lean/Lake, preserve theorem statements, and avoid final patches with `sorry`, `admit`, or new `axiom`. -The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. +The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. It can report and configure the official Numina runtime when the user explicitly wants that path, but the agent should still validate final Lean patches locally. diff --git a/README.md b/README.md index a3b2477..41da97c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # AI4Math Lean Agents -AI4Math Lean Agents is a guidance-first Codex skill for Lean 4 formal verification. The active coding agent directly reads, edits, and checks Lean code; the bundled CLI is only a deterministic helper toolbox for environment checks, Lean validation, patch review, and minimal failure handoff. +AI4Math Lean Agents is a guidance-first Codex skill for Lean 4 formal verification. The active coding agent directly reads, edits, and checks Lean code; the bundled CLI is only a deterministic helper toolbox for environment checks, Lean validation, optional official Numina runtime setup, patch review, and minimal failure handoff. The canonical skill package lives at: @@ -15,8 +15,9 @@ skills/AI4Math-Lean-Agents/ - Theorem formalization, proof repair, proof completion, and `sorry` completion. - Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. - Minimal failing Lean fragment extraction when a proof is blocked. +- Optional official `project-numina/numina-lean-agent` deployment/call flow, mediated by the coding agent. -This project does not deploy or call Numina. Numina is referenced only as workflow provenance in the skill documentation. +Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `.ai4math/numina-runtime/`. ## Repository Layout @@ -62,12 +63,15 @@ Run commands from the repository root: python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py env --cwd . python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --create-workspace +python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py check --cwd . --skip-build python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` The helper CLI is not the proof engine. The coding agent remains responsible for reading Lean errors, editing proofs, and choosing proof strategy. +For the optional Numina path, read `skills/AI4Math-Lean-Agents/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. + ## Validate ```bash diff --git a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md index f3e8fff..7f971f1 100644 --- a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md +++ b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md @@ -303,12 +303,12 @@ class NuminaRuntimePlanTests(unittest.TestCase): self.assertFalse(result["upstream"]["exists"]) self.assertIn("configure --setup-numina", result["recommended_next_action"]) - def test_configure_plan_includes_install_setup_and_sync(self) -> None: + def test_configure_plan_includes_install_setup_and_uv(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) self.make_upstream(root) - result = build_configure_plan(root, project_name="myproofs", skip_sync=False, dry_run=True) + result = build_configure_plan(root, project_name="myproofs", dry_run=True) commands = [action["command"] for action in result["actions"]] self.assertIn(["git", "fetch", "--all", "--tags"], commands) @@ -451,18 +451,16 @@ def numina_readiness(cwd: str | Path, target: str | Path | None = None) -> dict[ def build_configure_plan( cwd: str | Path, project_name: str, - skip_sync: bool = False, dry_run: bool = False, ) -> dict[str, Any]: install = build_install_plan(cwd, dry_run=dry_run) actions = list(install.get("actions", [])) upstream = _upstream_path(cwd) actions.append({"command": ["./setup.sh", project_name], "cwd": str(upstream / "tutorial")}) - if not skip_sync: - actions.extend([ - {"command": ["uv", "python", "install"], "cwd": str(upstream)}, - {"command": ["uv", "sync"], "cwd": str(upstream)}, - ]) + actions.extend([ + {"command": ["uv", "python", "install"], "cwd": str(upstream)}, + {"command": ["uv", "sync"], "cwd": str(upstream)}, + ]) return { "ok": bool(install.get("ok")), "status": "dry_run" if dry_run else "configure_plan_ready", @@ -699,7 +697,7 @@ Before returning `env`, add: "recommended_next_action": "pass --project-name when using --setup-numina", }) else: - numina_actions.append(build_configure_plan(cwd_path, project_name, skip_sync=skip_numina_sync, dry_run=dry_run)) + numina_actions.append(build_configure_plan(cwd_path, project_name, dry_run=dry_run)) env["numina_actions"] = numina_actions ``` @@ -708,7 +706,6 @@ In `ai4m_lean.py`, add parser args to `configure_parser`: ```python configure_parser.add_argument("--setup-numina", action="store_true") configure_parser.add_argument("--project-name", default=None) - configure_parser.add_argument("--skip-numina-sync", action="store_true") ``` Pass them into `configure()`. @@ -788,7 +785,7 @@ python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup After explaining the external API implications and confirming with the user, the coding agent can run an upstream Numina command from the cloned upstream checkout. A typical command shape is: ```bash -python -m scripts.run_claude run path/to/Foo.lean --prompt-file path/to/prompt.md --max-rounds 5 --result-dir .ai4math/numina-runtime/results/run +uv run python -m scripts.run_claude from-folder path/to/Foo.lean --prompt-file prompts/autosearch/main_entry.md --max-rounds 5 --result-dir .ai4math/numina-runtime/results/run ``` The existing direct local task envelope remains available: diff --git a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md index 9db44ca..ae915db 100644 --- a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md +++ b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md @@ -141,7 +141,7 @@ python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name mypr 1. 内部 Numina upstream install/update; 2. 内部 Numina setup/configure; -3. 可选 dependency sync,默认开启,可用 `--skip-numina-sync` 跳过。 +3. 按官方 README 执行 `uv python install` 和 `uv sync`。 ### 任务调用的交互原则 @@ -233,7 +233,7 @@ python scripts/ai4m_lean.py repair \ 实际上游命令等价于: ```bash -python -m scripts.run_claude run --prompt-file --max-rounds --result-dir +uv run python -m scripts.run_claude from-folder --prompt-file --max-rounds --result-dir ``` ### folder/batch helpers diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index 148cf68..9343470 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -1,33 +1,35 @@ --- name: ai4math-lean-agents -description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, theorem formalization, sorry completion, patch review, and minimal failure handoff. +description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, optional official Numina runtime deployment/calls, theorem formalization, sorry completion, patch review, and minimal failure handoff. --- # AI4Math Lean Agents -Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, or review of a Lean patch. The active coding agent is the Lean agent: it asks clarifying questions, reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, and iterates with the user. +Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or an official Numina Lean Agent run. The active coding agent is the Lean agent: it asks clarifying questions, reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, and iterates with the user. The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake commands, and repository context. Use helper commands only when their deterministic output is useful. -Numina is not deployed or called by this skill. Its public workflow is used only as design provenance in `references/numina_reverse_analysis.md`. +Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under ignored local state at `.ai4math/numina-runtime/`; the coding agent explains clone, setup, API-key, and Claude Code implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. ## Agent Playbook 1. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. 2. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available. 3. For standalone files, use or create `.ai4math/lean-workspace` only when a project context is needed. -4. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -5. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. -6. Preserve theorem statements unless the user explicitly approves a change. -7. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. -8. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. +4. If the user asks for original Numina behavior, or if an official Numina run would clearly help, inspect `doctor` readiness, explain the deployment/call, and proceed only after approval. +5. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. +6. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. +7. Preserve theorem statements unless the user explicitly approves a change. +8. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. +9. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. ## Helper Toolbox Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk: -- `env` / `doctor`: inspect Lean workspace and local tool availability. +- `env` / `doctor`: inspect Lean workspace, local tool availability, and optional Numina readiness. - `configure --create-workspace`: create or reuse the managed workspace. +- `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `.ai4math/numina-runtime/`. - `check`: run a structured Lean/Lake validation. - `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. - `minimize-failure`: extract a compact failing Lean fragment. @@ -36,11 +38,16 @@ Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk All helper commands emit machine-readable JSON on stdout. Human-readable diagnostics go to stderr or log files. +## Numina Runtime + +When using the official Numina runtime, follow `references/numina_runtime.md`. The helper code only plans, installs, and reports readiness; proof strategy remains a conversation between the user, the coding agent, local Lean checks, and, when approved, the official Numina runner. + ## Safety Rules -- Do not require Numina, Claude Code CLI, external model APIs, or API keys for this skill. +- Do not require Numina, Claude Code CLI, external model APIs, or API keys unless the user explicitly wants an official Numina deployment or run. - Do not commit local machine-specific paths. -- Do not call external APIs during `env`, `configure`, `check`, `review`, `detect-sorry`, tests, or dry-runs. +- Do not call external APIs during `env`, `doctor`, `check`, `review`, `detect-sorry`, tests, or dry-runs. +- Do not store secrets in tracked files; use environment variables or `.ai4math/numina-runtime/.env.local`. - Do not accept final Lean patches containing `sorry`, `admit`, or newly introduced `axiom`. - Do not silently weaken theorem statements or change existing project versions. - Do not let helper command availability override a better direct coding-agent path. @@ -49,7 +56,8 @@ All helper commands emit machine-readable JSON on stdout. Human-readable diagnos - Read `references/direct_lean_workflow.md` for the full guidance-first proof/repair/formalization loop. - Read `references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. +- Read `references/numina_runtime.md` when the user wants the official Numina deployment/call path. - Read `references/interactive_orchestration.md` when guiding user intake and task decomposition. - Read `references/review_checklist.md` before accepting a Lean patch. - Read `references/failure_taxonomy.md` when reporting a blocked proof. -- Read `references/numina_reverse_analysis.md` only when explaining which Numina mechanisms were distilled into this direct AI4Math skill. +- Read `references/numina_reverse_analysis.md` when explaining which Numina mechanisms were distilled and which are delegated to the optional official runtime. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index 038ad9a..abb0523 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents -short_description: Interactive Lean 4 verification with reusable mathlib workspaces. -default_prompt: Use the Lean agent playbook to directly formalize, prove, repair, review, or minimize this Lean task; use helper CLI checks only when useful. +short_description: Interactive Lean 4 verification with reusable mathlib workspaces and optional official Numina runtime setup. +default_prompt: Use the Lean agent playbook to formalize, prove, repair, review, or minimize this Lean task. Use helper CLI checks only when useful; use official Numina only through the approved human-in-the-loop runtime flow. diff --git a/skills/AI4Math-Lean-Agents/config/env.example b/skills/AI4Math-Lean-Agents/config/env.example index e41e5ae..3524a47 100644 --- a/skills/AI4Math-Lean-Agents/config/env.example +++ b/skills/AI4Math-Lean-Agents/config/env.example @@ -1,3 +1,4 @@ # Copy values into an ignored local file or export them manually. export AI4MATH_LEAN_WORKSPACE=".ai4math/lean-workspace" export AI4MATH_LEAN_TOOLCHAIN="leanprover/lean4:v4.28.0" +export AI4MATH_NUMINA_HOME=".ai4math/numina-runtime" diff --git a/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml b/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml new file mode 100644 index 0000000..d3600c2 --- /dev/null +++ b/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml @@ -0,0 +1,12 @@ +[numina] +upstream_url = "https://github.com/project-numina/numina-lean-agent" +runtime_home = ".ai4math/numina-runtime" +default_project_name = "myproofs" +default_prompt_file = "prompts/autosearch/main_entry.md" +default_max_rounds = 10 +store_secrets_here = false + +[policy] +require_user_approval_before_setup = true +require_user_approval_before_run = true +validate_outputs_with_local_lean = true diff --git a/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md b/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md index 28897d5..d62a20f 100644 --- a/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md +++ b/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md @@ -1,6 +1,6 @@ # Lean Runtime Configuration -This skill uses a direct coding-agent workflow. It does not deploy Numina, run a Numina Python environment, or require Claude Code/API credentials as a backend. +This skill uses a direct coding-agent workflow by default. It can also prepare an optional official Numina runtime under ignored local state when the user approves that path; see `numina_runtime.md` for deployment and call details. ## Local Layout @@ -8,6 +8,7 @@ This skill uses a direct coding-agent workflow. It does not deploy Numina, run a .ai4math/ ├── lean-workspace/ ├── lean-workspaces/ +├── numina-runtime/ ├── lean_agent.local.toml ├── logs/ └── failures/ @@ -24,7 +25,7 @@ python scripts/ai4m_lean.py doctor --cwd . python scripts/ai4m_lean.py env --cwd . ``` -Required local tools for the direct workflow are `git`, `python3`, `elan`, `lean`, and `lake`. `uv`, `claude`, Numina, and model API keys are not required by this skill. +Required local tools for the direct workflow are `git`, `python3`, `elan`, `lean`, and `lake`. Optional Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Numina and model API keys are not required for the direct workflow. ## Reusable Lean Workspace @@ -66,4 +67,5 @@ Environment overrides: ```bash export AI4MATH_LEAN_WORKSPACE=".ai4math/lean-workspace" export AI4MATH_LEAN_TOOLCHAIN="leanprover/lean4:v4.28.0" +export AI4MATH_NUMINA_HOME=".ai4math/numina-runtime" ``` diff --git a/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md b/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md index 3d06f2f..14b523b 100644 --- a/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md +++ b/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md @@ -1,6 +1,6 @@ # Numina Reverse Analysis for AI4Math -This reference records what was distilled from the public Numina Lean Agent workflow. It is design provenance only. The AI4Math Lean Agents skill does not install, deploy, configure, import, or call Numina at runtime. +This reference records what was distilled from the public Numina Lean Agent workflow and what remains delegated to the optional official runtime. For deployment/call instructions, use `numina_runtime.md`. ## Source Scope @@ -20,9 +20,9 @@ The goal is not to copy Numina prompts or reimplement Numina proof search. The g 6. When blocked, reduce the problem to the smallest useful failing Lean fragment. 7. Prefer reusable Lean workspaces so setup cost is not paid on every standalone problem. -## What Was Removed +## What Is Optional Runtime State -The direct AI4Math skill intentionally removes these runtime dependencies: +The default AI4Math loop still works without these runtime dependencies: - upstream Numina repository checkout; - Numina Python environment; @@ -31,7 +31,7 @@ The direct AI4Math skill intentionally removes these runtime dependencies: - API-key or login setup; - backend round streaming or benchmark execution. -Those concerns made sense for the original system, but they are not part of this skill's delivery target. +When the user wants original Numina behavior, those concerns are handled by the official upstream checkout under `.ai4math/numina-runtime/` and the human-in-the-loop flow in `numina_runtime.md`. ## Adapted Direct Workflow @@ -69,10 +69,12 @@ flowchart TD ## Practical Rule -If a future agent reads this file during normal Lean work, the action item is not "run Numina." The action item is: +If a future agent reads this file during normal Lean work, the default action item is: 1. use the direct skill CLI to verify local Lean readiness; 2. edit Lean directly; 3. run Lean/Lake checks frequently; 4. review safety constraints; 5. return a verified patch or minimal failure. + +If the user asks for original Numina behavior, switch to `numina_runtime.md`, explain setup/call implications, and validate all resulting Lean changes locally. diff --git a/skills/AI4Math-Lean-Agents/references/numina_runtime.md b/skills/AI4Math-Lean-Agents/references/numina_runtime.md new file mode 100644 index 0000000..2cf0bb3 --- /dev/null +++ b/skills/AI4Math-Lean-Agents/references/numina_runtime.md @@ -0,0 +1,31 @@ +# Optional Official Numina Runtime + +This skill can deploy and call the official `project-numina/numina-lean-agent` repository when the user wants the original Numina behavior. Treat it as an optional human-in-the-loop runtime, not as the default proof backend. + +## Agent Flow + +1. Clarify the user's intent: direct Lean repair, official Numina run, or a mix. +2. Run `doctor --cwd .` when useful and read the `numina` readiness block. +3. Explain what setup may do: clone the official repository, run `tutorial/setup.sh`, install or use `elan`, `lake`, `curl`, `uv`, and `claude`, and require model/API credentials for some tools. +4. After approval, run `configure --cwd . --setup-numina --project-name `. Use `--dry-run` first when the user wants to review commands. +5. For an official run, call the upstream runner from `.ai4math/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. +6. After Numina changes Lean files, use local `check`, `detect-sorry`, and `review` before accepting the patch. + +## Local State + +- Runtime root: `.ai4math/numina-runtime/` +- Upstream checkout: `.ai4math/numina-runtime/upstream/` +- Ignored credential file: `.ai4math/numina-runtime/.env.local` +- Suggested outputs: `.ai4math/numina-runtime/results/` + +Do not commit runtime state, API keys, generated results, or local machine paths. + +## Credentials + +Claude Code authentication can come from the user's normal Claude login or environment variables such as `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`. Numina's CLI skills may also need `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, or `AXLE_API_KEY`. + +The helper readiness report redacts values and only reports whether keys appear configured. + +## Boundary + +The AI4Math skill still owns delivery quality. Official Numina may propose or edit proofs, but final acceptance requires local Lean/Lake validation and the usual patch safety checks: no `sorry`, no `admit`, no newly introduced `axiom`, and no theorem statement drift unless explicitly approved. diff --git a/skills/AI4Math-Lean-Agents/schemas/config.schema.json b/skills/AI4Math-Lean-Agents/schemas/config.schema.json index a93587d..31aa411 100644 --- a/skills/AI4Math-Lean-Agents/schemas/config.schema.json +++ b/skills/AI4Math-Lean-Agents/schemas/config.schema.json @@ -5,7 +5,8 @@ "properties": { "lean": {"type": "object", "additionalProperties": true}, "agent": {"type": "object", "additionalProperties": true}, - "policy": {"type": "object", "additionalProperties": true} + "policy": {"type": "object", "additionalProperties": true}, + "numina": {"type": "object", "additionalProperties": true} }, "additionalProperties": false } diff --git a/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py b/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py index e9a55d5..092bb28 100644 --- a/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py +++ b/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py @@ -11,6 +11,7 @@ from detect_sorry import scan_file from direct_task import run_direct_task from extract_minimal_failure import extract +from numina_runtime import numina_readiness from tool_status import doctor from validate_patch import review_files from verify_delivery import verify as verify_delivery @@ -73,6 +74,8 @@ def build_parser() -> argparse.ArgumentParser: configure_parser.add_argument("--toolchain", default=None, help="Optional Lean toolchain for managed workspace") configure_parser.add_argument("--save-local", action="store_true") configure_parser.add_argument("--dry-run", action="store_true") + configure_parser.add_argument("--setup-numina", action="store_true", help="Install/configure official Numina runtime after review") + configure_parser.add_argument("--project-name", default=None, help="Lean project name for official Numina tutorial setup") for name in ("prove", "formalize", "repair", "complete-sorries"): proof = sub.add_parser(name, help=f"Prepare a direct coding-agent {name} task") @@ -129,6 +132,7 @@ def main(argv: list[str] | None = None) -> None: if args.command == "doctor": result = doctor(args.cwd) + result["numina"] = numina_readiness(args.cwd) _finish(result, args.json_output) if args.command == "check": @@ -147,6 +151,8 @@ def main(argv: list[str] | None = None) -> None: toolchain=args.toolchain, save_local=args.save_local, dry_run=args.dry_run, + setup_numina=args.setup_numina, + project_name=args.project_name, ) _finish(result, args.json_output, fail_code=EXIT_INTERACTIVE_REQUIRED) diff --git a/skills/AI4Math-Lean-Agents/scripts/common.py b/skills/AI4Math-Lean-Agents/scripts/common.py index 71eb948..778db24 100644 --- a/skills/AI4Math-Lean-Agents/scripts/common.py +++ b/skills/AI4Math-Lean-Agents/scripts/common.py @@ -116,6 +116,7 @@ def ensure_ai4math_gitignore(cwd: str | Path) -> Path: ".env.local", "lean-workspace/", "lean-workspaces/", + "numina-runtime/", "logs/", "failures/", ] diff --git a/skills/AI4Math-Lean-Agents/scripts/configure_lean.py b/skills/AI4Math-Lean-Agents/scripts/configure_lean.py index 950b148..24f91c3 100644 --- a/skills/AI4Math-Lean-Agents/scripts/configure_lean.py +++ b/skills/AI4Math-Lean-Agents/scripts/configure_lean.py @@ -6,6 +6,7 @@ from check_lean_project import find_project_root, read_mathlib_revision, read_toolchain from common import ensure_ai4math_gitignore, expand_path, read_config, run_command, update_local_toml +from numina_runtime import execute_configure_plan, numina_readiness from tool_status import find_tool @@ -74,6 +75,7 @@ def inspect_environment(cwd: str | Path = ".", config_path: str | Path | None = "mode": "direct-coding-agent", "backend": "none", "numina_required": False, + "numina_runtime": "optional-official-runtime", }, "lean": { "target": str(target_path), @@ -87,6 +89,7 @@ def inspect_environment(cwd: str | Path = ".", config_path: str | Path | None = "workspace_mode": lean.get("workspace_mode", "reuse-managed"), "align_workspace_versions": bool(lean.get("align_workspace_versions", True)), }, + "numina": numina_readiness(cwd_path, target=target_path), "missing_config": missing, "required_inputs": required_inputs, "recommended_next_action": "run configure --create-workspace or provide a Lake project" if missing else "ready", @@ -101,6 +104,8 @@ def configure( toolchain: str | None = None, save_local: bool = False, dry_run: bool = False, + setup_numina: bool = False, + project_name: str | None = None, ) -> dict[str, Any]: cwd_path = Path(cwd).resolve() if not dry_run: @@ -177,6 +182,23 @@ def configure( env = inspect_environment(cwd_path, config_path=config_path, target=target) env["workspace"] = workspace_info env["workspace_actions"] = workspace_actions + if setup_numina: + numina_result = execute_configure_plan( + cwd_path, + project_name=project_name, + dry_run=dry_run, + ) + env["numina"] = numina_result + if numina_result.get("ok"): + env["ok"] = True + env["status"] = numina_result.get("status", "numina_configured") + env["configuration_status"] = "numina_runtime_ready" if not dry_run else "numina_runtime_dry_run" + env["recommended_next_action"] = numina_result.get("recommended_next_action", "ready") + else: + env["ok"] = False + env["status"] = "interactive_required" if numina_result.get("status") == "missing_project_name" else numina_result.get("status", "numina_setup_failed") + env["configuration_status"] = "numina_runtime_missing_config" + env["recommended_next_action"] = numina_result.get("recommended_next_action", "review Numina setup requirements") if workspace_failed: env["ok"] = False env["status"] = "lean_workspace_setup_failed" diff --git a/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py b/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py new file mode 100644 index 0000000..740fbcc --- /dev/null +++ b/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py @@ -0,0 +1,414 @@ +from __future__ import annotations + +import os +import shlex +from pathlib import Path +from typing import Any + +from common import ENV_KEY_RE, ensure_ai4math_gitignore, expand_path, run_command +from tool_status import tool_versions + + +DEFAULT_UPSTREAM_URL = "https://github.com/project-numina/numina-lean-agent" +DEFAULT_PROMPT_FILE = "prompts/autosearch/main_entry.md" +CLAUDE_ENV_KEYS = ["ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL", "ANTHROPIC_MODEL"] +SKILL_ENV_KEYS = ["GEMINI_API_KEY", "OPENAI_API_KEY", "LEAN_LEANDEX_API_KEY", "AXLE_API_KEY"] + + +def runtime_root(cwd: str | Path) -> Path: + cwd_path = Path(cwd).resolve() + override = os.environ.get("AI4MATH_NUMINA_HOME") + if override: + return expand_path(override, cwd_path) or (cwd_path / ".ai4math" / "numina-runtime") + return cwd_path / ".ai4math" / "numina-runtime" + + +def runtime_paths(cwd: str | Path) -> dict[str, str]: + root = runtime_root(cwd) + return { + "root": str(root), + "upstream": str(root / "upstream"), + "projects": str(root / "upstream" / "projects"), + "results": str(root / "results"), + "env_local": str(root / ".env.local"), + "local_config": str(root / "numina_runtime.local.toml"), + "default_upstream_url": DEFAULT_UPSTREAM_URL, + } + + +def upstream_url() -> str: + return os.environ.get("AI4MATH_NUMINA_UPSTREAM_URL") or DEFAULT_UPSTREAM_URL + + +def upstream_ref() -> str | None: + return os.environ.get("AI4MATH_NUMINA_UPSTREAM_REF") or None + + +def _parse_env_file(path: Path) -> dict[str, str]: + if not path.exists(): + return {} + values: dict[str, str] = {} + for raw_line in path.read_text(encoding="utf-8", errors="replace").splitlines(): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + try: + parts = shlex.split(line, comments=True, posix=True) + except ValueError: + continue + if parts and parts[0] == "export": + parts = parts[1:] + for part in parts: + if "=" not in part: + continue + key, value = part.split("=", 1) + if ENV_KEY_RE.match(key): + values[key] = value + return values + + +def read_numina_env_local(cwd: str | Path) -> dict[str, str]: + return _parse_env_file(runtime_root(cwd) / ".env.local") + + +def _redact(value: str | None) -> str | None: + return "" if value else None + + +def credential_report(env: dict[str, str] | None = None) -> dict[str, Any]: + merged = dict(os.environ) + if env: + merged.update(env) + claude_variables = {key: _redact(merged.get(key)) for key in CLAUDE_ENV_KEYS} + skill_keys = {key: _redact(merged.get(key)) for key in SKILL_ENV_KEYS} + return { + "claude": { + "configured": bool(merged.get("ANTHROPIC_AUTH_TOKEN")), + "variables": claude_variables, + }, + "skill_keys": skill_keys, + "missing_skill_keys": [key for key in SKILL_ENV_KEYS if not merged.get(key)], + } + + +def _action(name: str, command: list[str], cwd: str | Path, *, dry_run: bool = False, timeout: int = 300) -> dict[str, Any]: + item: dict[str, Any] = { + "name": name, + "command": command, + "cwd": str(Path(cwd).resolve()), + "timeout": timeout, + } + if dry_run: + item["skipped"] = True + item["reason"] = "dry_run" + return item + + +def inspect_upstream(cwd: str | Path) -> dict[str, Any]: + upstream = runtime_root(cwd) / "upstream" + if not upstream.exists(): + return { + "exists": False, + "installed": False, + "path": str(upstream), + "status": "missing", + "remote": None, + "head": None, + "dirty": False, + } + if not (upstream / ".git").exists(): + return { + "exists": True, + "installed": False, + "path": str(upstream), + "status": "path_exists_non_git", + "remote": None, + "head": None, + "dirty": None, + } + remote = run_command(["git", "remote", "get-url", "origin"], cwd=upstream) + head = run_command(["git", "rev-parse", "HEAD"], cwd=upstream) + dirty = run_command(["git", "status", "--short"], cwd=upstream) + dirty_stdout = (dirty.get("stdout") or "").strip() + return { + "exists": True, + "installed": True, + "path": str(upstream), + "status": "installed", + "remote": (remote.get("stdout") or "").strip() if remote.get("ok") else None, + "head": (head.get("stdout") or "").strip() if head.get("ok") else None, + "dirty": bool(dirty_stdout), + "dirty_status": dirty_stdout.splitlines()[:20], + "dirty_check_ok": bool(dirty.get("ok")), + } + + +def build_install_plan(cwd: str | Path, *, dry_run: bool = False) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + root = runtime_root(cwd_path) + upstream = root / "upstream" + ref = upstream_ref() + actions: list[dict[str, Any]] = [] + + if upstream.exists() and not (upstream / ".git").exists(): + return { + "ok": False, + "status": "upstream_path_exists_non_git", + "paths": runtime_paths(cwd_path), + "actions": [], + "recommended_next_action": f"move or remove {upstream} before setup", + } + + if not upstream.exists(): + actions.append(_action( + "clone_numina_upstream", + ["git", "clone", upstream_url(), str(upstream)], + cwd_path, + dry_run=dry_run, + timeout=1800, + )) + else: + upstream_info = inspect_upstream(cwd_path) + if not upstream_info.get("dirty_check_ok", True): + return { + "ok": False, + "status": "upstream_status_failed", + "paths": runtime_paths(cwd_path), + "upstream": upstream_info, + "actions": [], + "recommended_next_action": "inspect the Numina upstream checkout before setup", + } + if upstream_info.get("dirty"): + return { + "ok": False, + "status": "dirty_upstream", + "paths": runtime_paths(cwd_path), + "upstream": upstream_info, + "actions": [], + "recommended_next_action": "review or commit local changes under the Numina upstream checkout before setup", + } + actions.append(_action( + "fetch_numina_upstream", + ["git", "fetch", "--all", "--prune"], + upstream, + dry_run=dry_run, + timeout=900, + )) + + if ref: + actions.append(_action( + "checkout_numina_ref", + ["git", "checkout", ref], + upstream, + dry_run=dry_run, + )) + + return { + "ok": True, + "status": "install_plan_ready", + "paths": runtime_paths(cwd_path), + "upstream_ref": ref, + "actions": actions, + "recommended_next_action": "review actions, then run configure --setup-numina --project-name ", + } + + +def build_configure_plan( + cwd: str | Path, + *, + project_name: str | None, + dry_run: bool = False, +) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + if not project_name: + return { + "ok": False, + "status": "missing_project_name", + "paths": runtime_paths(cwd_path), + "actions": [], + "recommended_next_action": "rerun configure --setup-numina with --project-name ", + } + + install = build_install_plan(cwd_path, dry_run=dry_run) + if not install.get("ok"): + return { + "ok": False, + "status": install.get("status", "install_plan_failed"), + "paths": runtime_paths(cwd_path), + "install": install, + "actions": [], + "recommended_next_action": install.get("recommended_next_action"), + } + + upstream = runtime_root(cwd_path) / "upstream" + actions = list(install.get("actions", [])) + actions.extend([ + _action( + "setup_numina_project", + ["./setup.sh", project_name], + upstream / "tutorial", + dry_run=dry_run, + timeout=3600, + ), + _action( + "uv_python_install", + ["uv", "python", "install"], + upstream, + dry_run=dry_run, + timeout=1800, + ), + _action( + "uv_sync", + ["uv", "sync"], + upstream, + dry_run=dry_run, + timeout=1800, + ), + ]) + + return { + "ok": True, + "status": "dry_run" if dry_run else "configure_plan_ready", + "paths": runtime_paths(cwd_path), + "project_name": project_name, + "install": install, + "actions": actions, + "recommended_next_action": "run official Numina on a buildable Lean project, then validate locally with check/review", + } + + +def execute_configure_plan( + cwd: str | Path, + *, + project_name: str | None, + dry_run: bool = False, +) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + plan = build_configure_plan(cwd_path, project_name=project_name, dry_run=dry_run) + if dry_run or not plan.get("ok"): + return plan + + ensure_ai4math_gitignore(cwd_path) + runtime_root(cwd_path).mkdir(parents=True, exist_ok=True) + env = read_numina_env_local(cwd_path) + executed: list[dict[str, Any]] = [] + ok = True + for action in plan.get("actions", []): + result = run_command( + action["command"], + cwd=action.get("cwd"), + timeout=int(action.get("timeout", 300)), + env=env if env else None, + ) + executed_action = dict(action) + executed_action.update({ + "ok": result.get("ok"), + "returncode": result.get("returncode"), + "stdout": result.get("stdout"), + "stderr": result.get("stderr"), + }) + executed.append(executed_action) + if not result.get("ok"): + ok = False + break + + plan["actions"] = executed + plan["ok"] = ok + plan["status"] = "configured" if ok else "numina_setup_failed" + if not ok: + plan["recommended_next_action"] = "inspect the failed setup action, then rerun configure --setup-numina after fixing the local environment" + return plan + + +def build_run_plan( + cwd: str | Path, + *, + file: str | Path, + mode: str = "from-folder", + prompt_file: str = DEFAULT_PROMPT_FILE, + result_dir: str | Path | None = None, + max_iters: int = 10, + reference_resources: str | None = None, +) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + target = expand_path(str(file), cwd_path) or Path(file).expanduser().resolve() + upstream = runtime_root(cwd_path) / "upstream" + if mode not in {"run", "batch", "from-folder"}: + return { + "ok": False, + "status": "unsupported_numina_mode", + "mode": mode, + "supported_modes": ["run", "batch", "from-folder"], + } + result_path = expand_path(str(result_dir), cwd_path) if result_dir else runtime_root(cwd_path) / "results" / "manual" + command = [ + "uv", + "run", + "python", + "-m", + "scripts.run_claude", + mode, + str(target), + "--prompt-file", + prompt_file, + "--max-rounds", + str(max_iters), + "--result-dir", + str(result_path), + ] + env = {} + if reference_resources: + env["REFERENCE_RESOURCES"] = reference_resources + return { + "ok": True, + "status": "run_plan_ready", + "cwd": str(upstream), + "mode": mode, + "command": command, + "env": env, + "target": str(target), + "result_dir": str(result_path), + "recommended_next_action": "explain the run to the user, execute only after approval, then validate the resulting Lean patch locally", + } + + +def build_batch_plan(cwd: str | Path, *, folder: str | Path, **kwargs: Any) -> dict[str, Any]: + return build_run_plan(cwd, file=folder, mode="from-folder", **kwargs) + + +def numina_readiness(cwd: str | Path, target: str | Path | None = None) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + env_local = read_numina_env_local(cwd_path) + credentials = credential_report(env_local) + tools = tool_versions(["git", "curl", "uv", "claude"]) + missing_tools = [name for name, info in tools.items() if not info.get("available")] + upstream = inspect_upstream(cwd_path) + missing: list[str] = [] + if missing_tools: + missing.append("tools") + if not upstream.get("installed"): + missing.append("upstream") + can_call_claude = bool(tools.get("claude", {}).get("available")) or credentials["claude"]["configured"] + if not can_call_claude: + missing.append("claude_cli_or_auth") + + result: dict[str, Any] = { + "ok": not missing, + "status": "ready" if not missing else "needs_setup", + "paths": runtime_paths(cwd_path), + "tools": tools, + "missing_tools": missing_tools, + "credentials": credentials, + "upstream": upstream, + "missing": missing, + "readiness": { + "can_clone_upstream": bool(tools.get("git", {}).get("available")), + "can_run_setup": all(tools.get(name, {}).get("available") for name in ("git", "curl")), + "can_sync_python": bool(tools.get("uv", {}).get("available")), + "can_call_claude_cli": can_call_claude, + }, + "recommended_next_action": "run configure --setup-numina --project-name " if missing else "ready to discuss an official Numina run", + } + if target: + result["target"] = str(Path(target).expanduser().resolve()) + return result diff --git a/skills/AI4Math-Lean-Agents/scripts/tool_status.py b/skills/AI4Math-Lean-Agents/scripts/tool_status.py index 512464d..ad8ba41 100644 --- a/skills/AI4Math-Lean-Agents/scripts/tool_status.py +++ b/skills/AI4Math-Lean-Agents/scripts/tool_status.py @@ -7,7 +7,7 @@ from common import run_command -DEFAULT_TOOLS = ["git", "python3", "elan", "lean", "lake"] +DEFAULT_TOOLS = ["git", "python3", "elan", "lean", "lake", "curl", "uv", "claude"] EXTRA_BIN_DIRS = [ Path.home() / ".elan" / "bin", Path.home() / ".local" / "bin", diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py index 5f56a8a..c3c0874 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py @@ -21,18 +21,21 @@ "SKILL.md", "agents/openai.yaml", "config/lean_agent.example.toml", + "config/numina_runtime.example.toml", "schemas/task.schema.json", "schemas/result.schema.json", "schemas/config.schema.json", "references/lean_runtime_configuration.md", "references/interactive_orchestration.md", "references/direct_lean_workflow.md", + "references/numina_runtime.md", "references/review_checklist.md", "references/failure_taxonomy.md", "references/numina_reverse_analysis.md", "scripts/ai4m_lean.py", "scripts/configure_lean.py", "scripts/direct_task.py", + "scripts/numina_runtime.py", "scripts/validate_patch.py", "scripts/extract_minimal_failure.py", ] @@ -102,6 +105,8 @@ def _guidance_first_check() -> dict[str, Any]: "## Agent Playbook", "## Helper Toolbox", "The bundled CLI is a helper toolbox, not the workflow driver.", + "Use official Numina through a human-in-the-loop runtime workflow.", + "Do not turn helper commands into a closed proof workflow.", "Do not let helper command availability override a better direct coding-agent path.", ] missing = [phrase for phrase in required_phrases if phrase not in text] @@ -164,6 +169,7 @@ def verify( checks = { "required_files": all(item["exists"] for item in files), "required_commands": REQUIRED_COMMANDS.issubset(commands), + "no_parallel_numina_commands": not any(command.startswith("numina") for command in commands), "schemas": all(item["ok"] for item in schemas), "guidance_first_skill": bool(guidance_first.get("ok")), "dry_run_prove": bool(dry_run.get("ok") and dry_run.get("status") == "dry_run"), @@ -219,7 +225,7 @@ def verify( "workspace_check": workspace_check, "workspace_build": workspace_build, "unit_tests": tests, - "external_api_note": "This direct workflow does not call Numina or external model APIs; the coding agent edits and checks Lean locally.", + "external_api_note": "env, doctor, check, review, tests, and dry-runs do not call external APIs. configure --setup-numina and approved official Numina runs may clone/install/call external tools, then final Lean changes must be validated locally.", } diff --git a/skills/AI4Math-Lean-Agents/tests/test_cli.py b/skills/AI4Math-Lean-Agents/tests/test_cli.py index 3339b2e..804d8c5 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_cli.py +++ b/skills/AI4Math-Lean-Agents/tests/test_cli.py @@ -78,6 +78,34 @@ def test_doctor_outputs_tool_report(self) -> None: self.assertTrue(payload["ok"]) self.assertIn("tools", payload) self.assertIn("readiness", payload) + self.assertIn("numina", payload) + self.assertIn("readiness", payload["numina"]) + + def test_configure_setup_numina_dry_run_outputs_official_upstream(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = subprocess.run( + [ + sys.executable, + str(CLI), + "configure", + "--cwd", + tmp, + "--setup-numina", + "--project-name", + "demo_project", + "--dry-run", + ], + text=True, + capture_output=True, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertIn("numina", payload) + self.assertEqual(payload["numina"]["status"], "dry_run") + commands = [action["command"] for action in payload["numina"]["actions"]] + self.assertIn("https://github.com/project-numina/numina-lean-agent", str(commands)) + self.assertIn(["./setup.sh", "demo_project"], commands) def test_lean_workspace_deploy_failure_uses_lean_exit_code(self) -> None: self.assertEqual( diff --git a/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py b/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py index e53cf2b..b8d87ff 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py +++ b/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py @@ -29,6 +29,8 @@ def test_existing_lean_project_is_direct_agent_ready(self) -> None: self.assertEqual(result["agent"]["backend"], "none") self.assertFalse(result["agent"]["numina_required"]) self.assertEqual(result["missing_config"], []) + self.assertIn("numina", result) + self.assertIn("readiness", result["numina"]) def test_save_local_writes_lean_agent_config(self) -> None: with tempfile.TemporaryDirectory() as tmp: @@ -62,6 +64,14 @@ def test_workspace_creation_failure_is_reported_as_lean_setup_failure(self) -> N self.assertEqual(result["status"], "lean_workspace_setup_failed") self.assertIn("retry configure --create-workspace", result["recommended_next_action"]) + def test_configure_setup_numina_requires_project_name(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + result = configure(Path(tmp), setup_numina=True, dry_run=True) + + self.assertFalse(result["numina"]["ok"]) + self.assertEqual(result["numina"]["status"], "missing_project_name") + self.assertIn("--project-name", result["numina"]["recommended_next_action"]) + if __name__ == "__main__": unittest.main() diff --git a/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py b/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py new file mode 100644 index 0000000..f2b828b --- /dev/null +++ b/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py @@ -0,0 +1,150 @@ +from __future__ import annotations + +import os +import sys +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" +sys.path.insert(0, str(SCRIPTS)) + +from common import ensure_ai4math_gitignore # noqa: E402 +from numina_runtime import ( # noqa: E402 + DEFAULT_UPSTREAM_URL, + build_configure_plan, + build_install_plan, + build_run_plan, + credential_report, + read_numina_env_local, + runtime_paths, +) + + +class NuminaRuntimePathTests(unittest.TestCase): + def test_runtime_paths_default_under_ai4math(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + paths = runtime_paths(Path(tmp)) + + root = Path(tmp).resolve() / ".ai4math" / "numina-runtime" + self.assertEqual(paths["root"], str(root)) + self.assertEqual(paths["upstream"], str(root / "upstream")) + self.assertEqual(paths["results"], str(root / "results")) + self.assertEqual(paths["default_upstream_url"], DEFAULT_UPSTREAM_URL) + + def test_runtime_paths_honor_ai4math_numina_home(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + custom = Path(tmp) / "custom-numina" + with patch.dict(os.environ, {"AI4MATH_NUMINA_HOME": str(custom)}, clear=False): + paths = runtime_paths(Path(tmp)) + + expected = Path(os.path.abspath(custom)) + self.assertEqual(paths["root"], str(expected)) + self.assertEqual(paths["upstream"], str(expected / "upstream")) + + def test_numina_runtime_is_ignored(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + gitignore = ensure_ai4math_gitignore(tmp) + + lines = gitignore.read_text(encoding="utf-8").splitlines() + + self.assertIn("numina-runtime/", lines) + + +class NuminaRuntimeCredentialTests(unittest.TestCase): + def test_env_local_is_read_from_numina_runtime_root(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + env_path = Path(tmp) / ".ai4math" / "numina-runtime" / ".env.local" + env_path.parent.mkdir(parents=True) + env_path.write_text( + "export ANTHROPIC_AUTH_TOKEN=secret-token\n" + "OPENAI_API_KEY=sk-test\n", + encoding="utf-8", + ) + + values = read_numina_env_local(Path(tmp)) + + self.assertEqual(values["ANTHROPIC_AUTH_TOKEN"], "secret-token") + self.assertEqual(values["OPENAI_API_KEY"], "sk-test") + + def test_credential_report_redacts_values(self) -> None: + report = credential_report({ + "ANTHROPIC_AUTH_TOKEN": "secret-token", + "OPENAI_API_KEY": "sk-test", + }) + + self.assertTrue(report["claude"]["configured"]) + self.assertEqual(report["claude"]["variables"]["ANTHROPIC_AUTH_TOKEN"], "") + self.assertEqual(report["skill_keys"]["OPENAI_API_KEY"], "") + self.assertNotIn("secret-token", str(report)) + + +class NuminaRuntimePlanTests(unittest.TestCase): + def test_install_plan_clones_official_upstream_when_missing(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + plan = build_install_plan(Path(tmp), dry_run=True) + + self.assertTrue(plan["ok"]) + self.assertEqual(plan["status"], "install_plan_ready") + self.assertEqual(plan["actions"][0]["command"][0:2], ["git", "clone"]) + self.assertEqual(plan["actions"][0]["command"][2], DEFAULT_UPSTREAM_URL) + + def test_install_plan_blocks_dirty_upstream(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + upstream = Path(tmp) / ".ai4math" / "numina-runtime" / "upstream" + upstream.mkdir(parents=True) + (upstream / ".git").mkdir() + + with patch("numina_runtime.run_command", return_value={ + "ok": True, + "returncode": 0, + "stdout": " M tutorial/foo.py\n", + "stderr": "", + "command": ["git", "status", "--short"], + }): + plan = build_install_plan(Path(tmp), dry_run=False) + + self.assertFalse(plan["ok"]) + self.assertEqual(plan["status"], "dirty_upstream") + self.assertEqual(plan["actions"], []) + + def test_configure_plan_uses_official_setup_and_uv_commands(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + upstream = Path(tmp) / ".ai4math" / "numina-runtime" / "upstream" + (upstream / ".git").mkdir(parents=True) + + with patch("numina_runtime.run_command", return_value={ + "ok": True, + "returncode": 0, + "stdout": "", + "stderr": "", + "command": ["git", "status", "--short"], + }): + plan = build_configure_plan(Path(tmp), project_name="demo_project", dry_run=True) + + commands = [action["command"] for action in plan["actions"]] + self.assertTrue(plan["ok"]) + self.assertIn(["./setup.sh", "demo_project"], commands) + self.assertIn(["uv", "python", "install"], commands) + self.assertIn(["uv", "sync"], commands) + self.assertNotIn(["uv", "run", "scripts/sync_projects.py"], commands) + + def test_run_plan_uses_official_runner_without_executing(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + theorem = root / "Demo.lean" + theorem.write_text("example : True := by\n trivial\n", encoding="utf-8") + upstream = root / ".ai4math" / "numina-runtime" / "upstream" + upstream.mkdir(parents=True) + + plan = build_run_plan(root, file=theorem, max_iters=3) + + self.assertTrue(plan["ok"]) + self.assertEqual(plan["status"], "run_plan_ready") + self.assertEqual(plan["command"][0:5], ["uv", "run", "python", "-m", "scripts.run_claude"]) + self.assertIn(str(Path(os.path.abspath(theorem))), plan["command"]) + + +if __name__ == "__main__": + unittest.main() From 9843c5c2bd5630a0241441730f5349bbf978b227 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Sun, 24 May 2026 22:56:09 +0800 Subject: [PATCH 10/37] Polish docs for open source release --- .codex/skills/ai4math-lean-agents/SKILL.md | 4 +- .cursor/rules/ai4math-lean-agents.mdc | 4 +- .opencode/agents/ai4math-lean-agents.md | 4 +- README.md | 28 +- .../2026-05-24-ai4math-numina-runtime.md | 930 ------------------ ...-05-24-numina-lean-agent-runtime-design.md | 336 ------- skills/AI4Math-Lean-Agents/SKILL.md | 4 +- 7 files changed, 29 insertions(+), 1281 deletions(-) delete mode 100644 docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md delete mode 100644 docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md diff --git a/.codex/skills/ai4math-lean-agents/SKILL.md b/.codex/skills/ai4math-lean-agents/SKILL.md index 9334e3a..55af262 100644 --- a/.codex/skills/ai4math-lean-agents/SKILL.md +++ b/.codex/skills/ai4math-lean-agents/SKILL.md @@ -1,6 +1,6 @@ --- name: ai4math-lean-agents -description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, theorem formalization, sorry completion, patch review, and minimal failure handoff. +description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, optional official Numina runtime deployment/calls, theorem formalization, sorry completion, patch review, and minimal failure handoff. --- # AI4Math Lean Agents Repo Shim @@ -11,4 +11,4 @@ This repo-local shim points to the canonical skill: ../../../skills/AI4Math-Lean-Agents/SKILL.md ``` -Read that file and follow it as the source of truth. The coding agent should directly operate Lean; helper CLI commands are guardrails, not a proof backend. +Read that file and follow it as the source of truth. The coding agent should directly operate Lean; helper CLI commands are guardrails, not a proof backend. Numina is optional and should be used only through the canonical human-in-the-loop runtime flow. diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index 7acbc4a..fbafe5f 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -The coding agent directly edits Lean and validates with Lean/Lake. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, patch review, `sorry` detection, or minimal failure handoff. +The coding agent directly edits Lean and validates with Lean/Lake. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. -Do not deploy Numina or require external model API keys for this workflow. +Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index 7b17cc8..a4dd6d9 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -1,6 +1,6 @@ # AI4Math Lean Agents -Use this agent for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, and minimal failure handoff. +Use this agent for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, optional official Numina runtime deployment/calls, and minimal failure handoff. Canonical workflow: @@ -13,5 +13,5 @@ Rules: - Directly inspect and edit Lean files. - Validate with Lean/Lake after meaningful edits. - Use helper CLI commands only as deterministic guardrails. -- Do not use Numina or external model APIs as a backend. +- Use official Numina only through the approved human-in-the-loop runtime flow. - Preserve theorem statements unless the user explicitly approves a change. diff --git a/README.md b/README.md index 41da97c..609f208 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # AI4Math Lean Agents -AI4Math Lean Agents is a guidance-first Codex skill for Lean 4 formal verification. The active coding agent directly reads, edits, and checks Lean code; the bundled CLI is only a deterministic helper toolbox for environment checks, Lean validation, optional official Numina runtime setup, patch review, and minimal failure handoff. +AI4Math Lean Agents is a guidance-first skill package for Lean 4 formal verification with coding agents. The active coding agent directly reads, edits, and checks Lean code; the bundled CLI is only a deterministic helper toolbox for environment checks, Lean validation, optional official Numina runtime setup, patch review, and minimal failure handoff. The canonical skill package lives at: @@ -28,10 +28,10 @@ Numina is optional. The public CLI does not expose a parallel `numina-*` workflo ├── GEMINI.md ├── README.md ├── LICENSE -├── .codex/ -├── .cursor/ ├── .github/ -├── .opencode/ +├── .codex/ # optional Codex adapter +├── .cursor/ # optional Cursor rule +├── .opencode/ # optional OpenCode agent └── skills/ └── AI4Math-Lean-Agents/ ├── SKILL.md @@ -44,16 +44,30 @@ Numina is optional. The public CLI does not expose a parallel `numina-*` workflo └── tests/ ``` -## Use With Codex +## Use With Coding Agents -Install or sync the skill folder into your Codex skills directory: +Point your coding agent at the canonical workflow: + +```text +skills/AI4Math-Lean-Agents/SKILL.md +``` + +The repository also includes lightweight adapters for several agent environments: + +- `AGENTS.md` for general repository-aware coding agents. +- `.codex/skills/ai4math-lean-agents/SKILL.md` as a Codex repo-local shim. +- `.cursor/rules/ai4math-lean-agents.mdc` for Cursor. +- `.opencode/agents/ai4math-lean-agents.md` for OpenCode. +- `CLAUDE.md` and `GEMINI.md` for agent-specific repository instructions. + +For Codex-style skill installation, sync the skill folder into the user skill directory: ```bash mkdir -p ~/.codex/skills rsync -a --delete skills/AI4Math-Lean-Agents/ ~/.codex/skills/ai4math-lean-agents/ ``` -Then ask Codex for Lean formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, or minimal failure extraction. +Then ask the coding agent for Lean formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, or minimal failure extraction. ## Helper Commands diff --git a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md b/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md deleted file mode 100644 index 7f971f1..0000000 --- a/docs/superpowers/plans/2026-05-24-ai4math-numina-runtime.md +++ /dev/null @@ -1,930 +0,0 @@ -# AI4Math Numina Runtime Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** 改造现有 `AI4Math-Lean-Agents` skill,使 coding agent 能通过交互式流程部署并调用官方 `project-numina/numina-lean-agent`,同时保留现有 Lean guardrails 和 direct task envelope。 - -**Architecture:** 新增 `scripts/numina_runtime.py` 作为内部 runtime helper,负责本地路径、credential redaction、上游状态、安装/配置计划和官方 runner command plan。公开 CLI 不新增一组平行的 `numina-*` 命令;`doctor` 展示 Numina readiness,`configure --setup-numina` 负责可审阅的安装/配置,`SKILL.md` 和 `references/numina_runtime.md` 指导 coding agent 何时向用户说明、何时调用上游 Numina、何时使用本地 guardrails。现有 `prove/repair/formalize/complete-sorries/batch` 保持 task envelope/辅助入口,不强制改造成 Numina 流水线。 - -**Tech Stack:** Python 3 standard library, `unittest`, existing Lean/Lake helper modules, `git`, `uv`, `claude` CLI, official `project-numina/numina-lean-agent`. - ---- - -## File Structure - -- Create `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: internal deterministic Numina runtime wrapper. It has no external API calls in `doctor`, `dry_run`, or tests. -- Create `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: offline tests for runtime paths, credential redaction, install/configure plans, dirty upstream protection, and runner command construction. -- Create `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml`: tracked example config. -- Create `skills/AI4Math-Lean-Agents/references/numina_runtime.md`: operator reference for official Numina deployment through existing commands. -- Modify `skills/AI4Math-Lean-Agents/scripts/common.py`: add `numina-runtime/` to `.ai4math/.gitignore`. -- Modify `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: include `curl`, `uv`, and `claude` in tool reporting. -- Modify `skills/AI4Math-Lean-Agents/scripts/configure_lean.py`: add Numina readiness to `inspect_environment`; add `setup_numina`, `project_name`, `skip_numina_sync` handling to `configure`. -- Modify `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py`: wire `configure --setup-numina`; keep task commands as existing envelopes. -- Modify `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py`: require new runtime files and update policy checks. -- Modify docs: `skills/AI4Math-Lean-Agents/SKILL.md`, `README.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `skills/AI4Math-Lean-Agents/agents/openai.yaml`, `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`. - ---- - -### Task 1: Internal Runtime Paths, Credentials, and Gitignore - -**Files:** -- Create: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` -- Create: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` -- Modify: `skills/AI4Math-Lean-Agents/scripts/common.py` - -- [ ] **Step 1: Write failing tests** - -Create `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: - -```python -from __future__ import annotations - -import os -import sys -import tempfile -import unittest -from pathlib import Path -from unittest.mock import patch - -SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" -sys.path.insert(0, str(SCRIPTS)) - -from common import ensure_ai4math_gitignore # noqa: E402 -from numina_runtime import ( # noqa: E402 - DEFAULT_UPSTREAM_URL, - credential_report, - read_numina_env_local, - runtime_paths, -) - - -class NuminaRuntimePathTests(unittest.TestCase): - def test_runtime_paths_default_under_ai4math(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - paths = runtime_paths(Path(tmp)) - - root = Path(tmp).resolve() / ".ai4math" / "numina-runtime" - self.assertEqual(paths["root"], str(root)) - self.assertEqual(paths["upstream"], str(root / "upstream")) - self.assertEqual(paths["results"], str(root / "results")) - self.assertEqual(paths["default_upstream_url"], DEFAULT_UPSTREAM_URL) - - def test_runtime_paths_honor_ai4math_numina_home(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - custom = Path(tmp) / "custom-numina" - with patch.dict(os.environ, {"AI4MATH_NUMINA_HOME": str(custom)}, clear=False): - paths = runtime_paths(Path(tmp)) - - self.assertEqual(paths["root"], str(custom.resolve())) - self.assertEqual(paths["upstream"], str(custom.resolve() / "upstream")) - - def test_numina_runtime_is_ignored(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - gitignore = ensure_ai4math_gitignore(tmp) - - lines = gitignore.read_text(encoding="utf-8").splitlines() - - self.assertIn("numina-runtime/", lines) - - -class NuminaRuntimeCredentialTests(unittest.TestCase): - def test_env_local_is_read_from_numina_runtime_root(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - env_path = Path(tmp) / ".ai4math" / "numina-runtime" / ".env.local" - env_path.parent.mkdir(parents=True) - env_path.write_text( - "export ANTHROPIC_AUTH_TOKEN=secret-token\n" - "OPENAI_API_KEY=sk-test\n", - encoding="utf-8", - ) - - values = read_numina_env_local(Path(tmp)) - - self.assertEqual(values["ANTHROPIC_AUTH_TOKEN"], "secret-token") - self.assertEqual(values["OPENAI_API_KEY"], "sk-test") - - def test_credential_report_redacts_values(self) -> None: - report = credential_report({ - "ANTHROPIC_AUTH_TOKEN": "secret-token", - "OPENAI_API_KEY": "sk-test", - }) - - self.assertTrue(report["claude"]["configured"]) - self.assertEqual(report["claude"]["variables"]["ANTHROPIC_AUTH_TOKEN"], "") - self.assertEqual(report["skill_keys"]["OPENAI_API_KEY"], "") - self.assertNotIn("secret-token", str(report)) - - -if __name__ == "__main__": - unittest.main() -``` - -- [ ] **Step 2: Verify tests fail** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py -``` - -Expected: FAIL with missing `numina_runtime` module or missing imported functions. - -- [ ] **Step 3: Implement runtime path and credential helpers** - -Create `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: - -```python -from __future__ import annotations - -import os -import shlex -from pathlib import Path -from typing import Any - -from common import expand_path - - -DEFAULT_UPSTREAM_URL = "https://github.com/project-numina/numina-lean-agent" -CLAUDE_ENV_KEYS = ["ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL", "ANTHROPIC_MODEL"] -SKILL_ENV_KEYS = ["GEMINI_API_KEY", "OPENAI_API_KEY", "LEAN_LEANDEX_API_KEY", "AXLE_API_KEY"] - - -def runtime_root(cwd: str | Path) -> Path: - cwd_path = Path(cwd).resolve() - override = os.environ.get("AI4MATH_NUMINA_HOME") - if override: - return expand_path(override, cwd_path) or (cwd_path / ".ai4math" / "numina-runtime") - return cwd_path / ".ai4math" / "numina-runtime" - - -def runtime_paths(cwd: str | Path) -> dict[str, str]: - root = runtime_root(cwd) - return { - "root": str(root), - "upstream": str(root / "upstream"), - "projects": str(root / "projects"), - "results": str(root / "results"), - "env_local": str(root / ".env.local"), - "local_config": str(root / "numina_runtime.local.toml"), - "default_upstream_url": DEFAULT_UPSTREAM_URL, - } - - -def _parse_env_file(path: Path) -> dict[str, str]: - if not path.exists(): - return {} - values: dict[str, str] = {} - for raw_line in path.read_text(encoding="utf-8", errors="replace").splitlines(): - line = raw_line.strip() - if not line or line.startswith("#"): - continue - parts = shlex.split(line, comments=True, posix=True) - if parts and parts[0] == "export": - parts = parts[1:] - for part in parts: - if "=" in part: - key, value = part.split("=", 1) - values[key] = value - return values - - -def read_numina_env_local(cwd: str | Path) -> dict[str, str]: - return _parse_env_file(runtime_root(cwd) / ".env.local") - - -def _redact(value: str | None) -> str | None: - return "" if value else None - - -def credential_report(env: dict[str, str] | None = None) -> dict[str, Any]: - merged = dict(os.environ) - if env: - merged.update(env) - claude_variables = {key: _redact(merged.get(key)) for key in CLAUDE_ENV_KEYS} - skill_keys = {key: _redact(merged.get(key)) for key in SKILL_ENV_KEYS} - return { - "claude": { - "configured": bool(merged.get("ANTHROPIC_AUTH_TOKEN")), - "variables": claude_variables, - }, - "skill_keys": skill_keys, - "missing_skill_keys": [key for key in SKILL_ENV_KEYS if not merged.get(key)], - } -``` - -Modify the `entries` list in `skills/AI4Math-Lean-Agents/scripts/common.py`: - -```python - "numina-runtime/", -``` - -- [ ] **Step 4: Verify focused tests pass** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py -``` - -Expected: PASS. - -- [ ] **Step 5: Commit** - -```bash -git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ - skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py \ - skills/AI4Math-Lean-Agents/scripts/common.py -git commit -m "Add Numina runtime helpers" -``` - ---- - -### Task 2: Internal Install, Configure, and Runner Plans - -**Files:** -- Modify: `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py` -- Modify: `skills/AI4Math-Lean-Agents/scripts/tool_status.py` - -- [ ] **Step 1: Add failing tests for internal plans** - -Append to `skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py`: - -```python -from numina_runtime import ( # noqa: E402 - build_batch_plan, - build_configure_plan, - build_install_plan, - build_run_plan, - numina_readiness, -) - - -class NuminaRuntimePlanTests(unittest.TestCase): - def make_lake_project(self, root: Path) -> Path: - (root / "lean-toolchain").write_text("leanprover/lean4:v4.28.0\n", encoding="utf-8") - (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") - target = root / "Main.lean" - target.write_text("example : True := by trivial\n", encoding="utf-8") - return target - - def make_upstream(self, root: Path) -> Path: - upstream = root / ".ai4math" / "numina-runtime" / "upstream" - upstream.mkdir(parents=True) - (upstream / ".git").mkdir() - return upstream - - def test_install_dry_run_uses_official_upstream(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - result = build_install_plan(Path(tmp), dry_run=True) - - self.assertTrue(result["ok"]) - self.assertEqual(result["status"], "dry_run") - self.assertEqual(result["upstream_url"], DEFAULT_UPSTREAM_URL) - self.assertEqual(result["actions"][0]["command"][:2], ["git", "clone"]) - - def test_dirty_upstream_blocks_non_dry_run_update(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - upstream = self.make_upstream(Path(tmp)) - with patch("numina_runtime.run_command") as run: - run.return_value = {"ok": True, "stdout": " M file.py\n", "stderr": "", "returncode": 0} - - result = build_install_plan(Path(tmp), dry_run=False) - - self.assertEqual(str(upstream), result["upstream"]["path"]) - self.assertFalse(result["ok"]) - self.assertEqual(result["status"], "upstream_dirty") - - def test_readiness_reports_missing_runtime(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - result = numina_readiness(Path(tmp)) - - self.assertTrue(result["ok"]) - self.assertFalse(result["upstream"]["exists"]) - self.assertIn("configure --setup-numina", result["recommended_next_action"]) - - def test_configure_plan_includes_install_setup_and_uv(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - self.make_upstream(root) - - result = build_configure_plan(root, project_name="myproofs", dry_run=True) - - commands = [action["command"] for action in result["actions"]] - self.assertIn(["git", "fetch", "--all", "--tags"], commands) - self.assertIn(["./setup.sh", "myproofs"], commands) - self.assertIn(["uv", "python", "install"], commands) - self.assertIn(["uv", "sync"], commands) - - def test_run_plan_requires_lake_project(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - target = Path(tmp) / "Main.lean" - target.write_text("example : True := by trivial\n", encoding="utf-8") - - result = build_run_plan(Path(tmp), target, prompt_file=None, prompt="prove it", max_rounds=5, result_dir=None, dry_run=True) - - self.assertFalse(result["ok"]) - self.assertEqual(result["status"], "missing_lake_project") - - def test_run_plan_builds_official_runner_command(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - root = Path(tmp) - self.make_upstream(root) - target = self.make_lake_project(root) - prompt = root / "prompt.md" - prompt.write_text("prove the target\n", encoding="utf-8") - - result = build_run_plan(root, target, prompt_file=prompt, prompt=None, max_rounds=7, result_dir=None, dry_run=True) - - self.assertTrue(result["ok"]) - self.assertEqual(result["status"], "dry_run") - self.assertEqual(result["command"][:4], ["python", "-m", "scripts.run_claude", "run"]) - self.assertIn("--max-rounds", result["command"]) - self.assertIn("7", result["command"]) - - def test_batch_plan_requires_existing_target(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - result = build_batch_plan(Path(tmp), Path(tmp) / "missing", prompt_file=None, max_rounds=5, result_dir=None, dry_run=True) - - self.assertFalse(result["ok"]) - self.assertEqual(result["status"], "file_not_found") -``` - -- [ ] **Step 2: Verify tests fail** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py -``` - -Expected: FAIL with missing plan functions. - -- [ ] **Step 3: Implement internal plan functions** - -Append to `skills/AI4Math-Lean-Agents/scripts/numina_runtime.py`: - -```python -from check_lean_project import find_project_root -from common import run_command -from tool_status import tool_versions - - -def upstream_url() -> str: - return os.environ.get("NUMINA_LEAN_AGENT_REPO") or DEFAULT_UPSTREAM_URL - - -def upstream_ref() -> str | None: - return os.environ.get("NUMINA_LEAN_AGENT_REF") or None - - -def _upstream_path(cwd: str | Path) -> Path: - return Path(runtime_paths(cwd)["upstream"]) - - -def inspect_upstream(cwd: str | Path) -> dict[str, Any]: - upstream = _upstream_path(cwd) - exists = upstream.exists() - is_git = (upstream / ".git").exists() - result: dict[str, Any] = { - "path": str(upstream), - "exists": exists, - "is_git": is_git, - "dirty": False, - "commit": None, - } - if not is_git: - return result - status = run_command(["git", "status", "--short"], cwd=upstream, timeout=30) - result["dirty"] = bool((status.get("stdout") or "").strip()) - rev = run_command(["git", "rev-parse", "HEAD"], cwd=upstream, timeout=30) - if rev.get("ok"): - result["commit"] = (rev.get("stdout") or "").strip() - return result - - -def build_install_plan(cwd: str | Path, dry_run: bool = False) -> dict[str, Any]: - upstream = inspect_upstream(cwd) - if upstream["exists"] and upstream["is_git"] and upstream["dirty"] and not dry_run: - return { - "ok": False, - "status": "upstream_dirty", - "upstream": upstream, - "recommended_next_action": "clean, commit, or stash .ai4math/numina-runtime/upstream before updating", - } - upstream_path = _upstream_path(cwd) - actions: list[dict[str, Any]] = [] - if not upstream_path.exists(): - actions.append({"command": ["git", "clone", upstream_url(), str(upstream_path)], "cwd": str(Path(cwd).resolve())}) - else: - actions.append({"command": ["git", "fetch", "--all", "--tags"], "cwd": str(upstream_path)}) - if upstream_ref(): - actions.append({"command": ["git", "checkout", upstream_ref() or ""], "cwd": str(upstream_path)}) - return { - "ok": True, - "status": "dry_run" if dry_run else "install_plan_ready", - "upstream_url": upstream_url(), - "upstream_ref": upstream_ref(), - "upstream": upstream, - "actions": actions, - } - - -def numina_readiness(cwd: str | Path, target: str | Path | None = None) -> dict[str, Any]: - env_local = read_numina_env_local(cwd) - upstream = inspect_upstream(cwd) - missing = [] - if not upstream["exists"]: - missing.append("numina_runtime") - return { - "ok": True, - "status": "reported", - "runtime_paths": runtime_paths(cwd), - "tools": tool_versions(["git", "curl", "uv", "elan", "lean", "lake", "claude", "python3"]), - "credentials": credential_report(env_local), - "upstream": upstream, - "missing": missing, - "recommended_next_action": "run configure --setup-numina --project-name " if missing else "ready for Numina task commands", - } - - -def build_configure_plan( - cwd: str | Path, - project_name: str, - dry_run: bool = False, -) -> dict[str, Any]: - install = build_install_plan(cwd, dry_run=dry_run) - actions = list(install.get("actions", [])) - upstream = _upstream_path(cwd) - actions.append({"command": ["./setup.sh", project_name], "cwd": str(upstream / "tutorial")}) - actions.extend([ - {"command": ["uv", "python", "install"], "cwd": str(upstream)}, - {"command": ["uv", "sync"], "cwd": str(upstream)}, - ]) - return { - "ok": bool(install.get("ok")), - "status": "dry_run" if dry_run else "configure_plan_ready", - "project_name": project_name, - "actions": actions, - } - - -def _default_result_dir(cwd: str | Path, task_type: str) -> Path: - return Path(runtime_paths(cwd)["results"]) / task_type - - -def _validate_lake_target(path: Path) -> tuple[Path | None, dict[str, Any] | None]: - root = find_project_root(path) - if root is None: - return None, {"ok": False, "status": "missing_lake_project", "target": str(path)} - return root, None - - -def build_run_plan( - cwd: str | Path, - file: str | Path, - prompt_file: str | Path | None, - prompt: str | None, - max_rounds: int, - result_dir: str | Path | None, - dry_run: bool = False, -) -> dict[str, Any]: - target = Path(file).expanduser().resolve() - if not target.exists(): - return {"ok": False, "status": "file_not_found", "target": str(target)} - project_root, error = _validate_lake_target(target) - if error: - return error - upstream = _upstream_path(cwd) - if not upstream.exists(): - return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run configure --setup-numina --project-name "} - if prompt_file is None and not prompt: - return {"ok": False, "status": "missing_prompt"} - output_dir = Path(result_dir).expanduser().resolve() if result_dir else _default_result_dir(cwd, "run") - command = ["python", "-m", "scripts.run_claude", "run", str(target)] - if prompt_file: - command.extend(["--prompt-file", str(Path(prompt_file).expanduser().resolve())]) - if prompt: - command.extend(["--prompt", prompt]) - command.extend(["--max-rounds", str(max_rounds), "--result-dir", str(output_dir)]) - return { - "ok": True, - "status": "dry_run" if dry_run else "numina_run_ready", - "command": command, - "cwd": str(upstream), - "project_root": str(project_root), - "result_dir": str(output_dir), - } - - -def build_batch_plan( - cwd: str | Path, - folder: str | Path, - prompt_file: str | Path | None, - max_rounds: int, - result_dir: str | Path | None, - dry_run: bool = False, -) -> dict[str, Any]: - folder_path = Path(folder).expanduser().resolve() - if not folder_path.exists(): - return {"ok": False, "status": "file_not_found", "target": str(folder_path)} - project_root, error = _validate_lake_target(folder_path) - if error: - return error - upstream = _upstream_path(cwd) - if not upstream.exists(): - return {"ok": False, "status": "missing_numina_runtime", "recommended_next_action": "run configure --setup-numina --project-name "} - output_dir = Path(result_dir).expanduser().resolve() if result_dir else _default_result_dir(cwd, "batch") - command = ["python", "-m", "scripts.run_claude", "from-folder", str(folder_path), "--max-rounds", str(max_rounds), "--result-dir", str(output_dir)] - if prompt_file: - command.extend(["--prompt-file", str(Path(prompt_file).expanduser().resolve())]) - return { - "ok": True, - "status": "dry_run" if dry_run else "numina_batch_ready", - "command": command, - "cwd": str(upstream), - "project_root": str(project_root), - "result_dir": str(output_dir), - } -``` - -- [ ] **Step 4: Update tool status defaults** - -Modify `DEFAULT_TOOLS` in `skills/AI4Math-Lean-Agents/scripts/tool_status.py`: - -```python -DEFAULT_TOOLS = ["git", "python3", "curl", "uv", "elan", "lean", "lake", "claude"] -``` - -- [ ] **Step 5: Verify focused tests pass** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py -``` - -Expected: PASS. - -- [ ] **Step 6: Commit** - -```bash -git add skills/AI4Math-Lean-Agents/scripts/numina_runtime.py \ - skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py \ - skills/AI4Math-Lean-Agents/scripts/tool_status.py -git commit -m "Add Numina runtime command plans" -``` - ---- - -### Task 3: Configure and Doctor Use Runtime Readiness - -**Files:** -- Modify: `skills/AI4Math-Lean-Agents/scripts/configure_lean.py` -- Modify: `skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` - -- [ ] **Step 1: Add failing tests** - -Append to `skills/AI4Math-Lean-Agents/tests/test_configure_lean.py`: - -```python - def test_inspect_environment_includes_numina_runtime_summary(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - result = inspect_environment(tmp) - - self.assertIn("numina", result) - self.assertFalse(result["numina"]["upstream"]["exists"]) - self.assertIn("configure --setup-numina", result["numina"]["recommended_next_action"]) -``` - -Append to `skills/AI4Math-Lean-Agents/tests/test_cli.py`: - -```python - def test_configure_setup_numina_dry_run_outputs_official_upstream(self) -> None: - with tempfile.TemporaryDirectory() as tmp: - result = subprocess.run( - [ - sys.executable, - str(CLI), - "configure", - "--cwd", - tmp, - "--setup-numina", - "--project-name", - "myproofs", - "--dry-run", - ], - text=True, - capture_output=True, - check=False, - ) - - self.assertEqual(result.returncode, 0, result.stderr) - payload = json.loads(result.stdout) - self.assertIn("numina_actions", payload) - commands = [action["command"] for action in payload["numina_actions"][0]["actions"]] - self.assertIn(["git", "clone", "https://github.com/project-numina/numina-lean-agent", str(Path(tmp).resolve() / ".ai4math" / "numina-runtime" / "upstream")], commands) -``` - -- [ ] **Step 2: Verify tests fail** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest \ - skills/AI4Math-Lean-Agents/tests/test_configure_lean.py \ - skills/AI4Math-Lean-Agents/tests/test_cli.py -``` - -Expected: FAIL because `numina` summary and `--setup-numina` parser args are absent. - -- [ ] **Step 3: Add Numina readiness to environment inspection** - -Modify imports in `skills/AI4Math-Lean-Agents/scripts/configure_lean.py`: - -```python -from numina_runtime import build_configure_plan, numina_readiness -``` - -In `inspect_environment`, before the return: - -```python - numina = numina_readiness(cwd_path, target=target_path) -``` - -Add to the returned dict: - -```python - "numina": { - "status": numina.get("status"), - "runtime_paths": numina.get("runtime_paths"), - "upstream": numina.get("upstream"), - "missing": numina.get("missing", []), - "recommended_next_action": numina.get("recommended_next_action"), - }, -``` - -- [ ] **Step 4: Add configure setup arguments** - -Change `configure()` signature in `configure_lean.py`: - -```python -def configure( - cwd: str | Path = ".", - config_path: str | Path | None = None, - target: str | Path | None = None, - create_workspace: bool = False, - toolchain: str | None = None, - save_local: bool = False, - dry_run: bool = False, - setup_numina: bool = False, - project_name: str | None = None, - skip_numina_sync: bool = False, -) -> dict[str, Any]: -``` - -Before returning `env`, add: - -```python - numina_actions: list[dict[str, Any]] = [] - if setup_numina: - if not project_name: - numina_actions.append({ - "ok": False, - "status": "missing_project_name", - "recommended_next_action": "pass --project-name when using --setup-numina", - }) - else: - numina_actions.append(build_configure_plan(cwd_path, project_name, dry_run=dry_run)) - env["numina_actions"] = numina_actions -``` - -In `ai4m_lean.py`, add parser args to `configure_parser`: - -```python - configure_parser.add_argument("--setup-numina", action="store_true") - configure_parser.add_argument("--project-name", default=None) -``` - -Pass them into `configure()`. - -- [ ] **Step 5: Verify focused tests pass** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest \ - skills/AI4Math-Lean-Agents/tests/test_configure_lean.py \ - skills/AI4Math-Lean-Agents/tests/test_cli.py -``` - -Expected: PASS. - -- [ ] **Step 6: Commit** - -```bash -git add skills/AI4Math-Lean-Agents/scripts/configure_lean.py \ - skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py \ - skills/AI4Math-Lean-Agents/tests/test_configure_lean.py \ - skills/AI4Math-Lean-Agents/tests/test_cli.py -git commit -m "Add Numina setup through configure" -``` - ---- - -### Task 4: Documentation and Delivery Verification - -**Files:** -- Create: `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml` -- Create: `skills/AI4Math-Lean-Agents/references/numina_runtime.md` -- Modify: `skills/AI4Math-Lean-Agents/SKILL.md` -- Modify: `skills/AI4Math-Lean-Agents/agents/openai.yaml` -- Modify: `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md` -- Modify: `README.md`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` -- Modify: `skills/AI4Math-Lean-Agents/scripts/verify_delivery.py` -- Modify: `skills/AI4Math-Lean-Agents/tests/test_cli.py` - -- [ ] **Step 1: Add runtime config and reference** - -Create `skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml`: - -```toml -[numina] -upstream_url = "https://github.com/project-numina/numina-lean-agent" -runtime_root = ".ai4math/numina-runtime" -default_ref = "main" -results_dir = ".ai4math/numina-runtime/results" -sync_dependencies_by_default = true - -[credentials] -read_env_local = true -env_local_path = ".ai4math/numina-runtime/.env.local" -``` - -Create `skills/AI4Math-Lean-Agents/references/numina_runtime.md`: - -```markdown -# Numina Runtime Workflow - -Use this reference when the user wants official Numina deployment or invocation through AI4Math Lean Agents. - -## First-Time Setup - -Run: - -```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs -``` - -## Invocation - -After explaining the external API implications and confirming with the user, the coding agent can run an upstream Numina command from the cloned upstream checkout. A typical command shape is: - -```bash -uv run python -m scripts.run_claude from-folder path/to/Foo.lean --prompt-file prompts/autosearch/main_entry.md --max-rounds 5 --result-dir .ai4math/numina-runtime/results/run -``` - -The existing direct local task envelope remains available: - -```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file path/to/Foo.lean --dry-run -``` - -## Safety - -The Numina route may call external model APIs through upstream Numina and Claude. Never print secret values. Use `.ai4math/numina-runtime/.env.local` or the shell environment for credentials. -``` - -- [ ] **Step 2: Update skill and root docs** - -Update: - -- `skills/AI4Math-Lean-Agents/SKILL.md`: workflow is official Numina runtime assisted and human-in-the-loop; direct local Lean guardrails remain part of diagnosis and final validation. -- `README.md`: show `doctor`, `configure --setup-numina`, an example upstream `scripts.run_claude` command, and existing `repair/prove --dry-run` task-envelope usage. -- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`: replace no-Numina policy with official Numina runtime default plus external API warning. -- `skills/AI4Math-Lean-Agents/agents/openai.yaml`: mention official Numina runtime. -- `skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md`: add a top note that it is historical background and no longer defines a no-call policy. - -- [ ] **Step 3: Update delivery verifier** - -Modify `REQUIRED_FILES` in `verify_delivery.py`: - -```python - "config/numina_runtime.example.toml", - "references/numina_runtime.md", - "scripts/numina_runtime.py", -``` - -Do not add public `numina-*` commands to `REQUIRED_COMMANDS`. The required command set remains centered on existing `doctor`, `configure`, and task commands. - -Replace `_guidance_first_check()` required phrases with: - -```python - required_phrases = [ - "## Agent Playbook", - "## Helper Toolbox", - "official Numina runtime", - "Use official Numina through a human-in-the-loop runtime workflow", - ] -``` - -Update `external_api_note`: - -```python - "external_api_note": "The Numina runtime workflow may call upstream Numina, Claude, and external model APIs after user-facing explanation/confirmation. Guardrail commands and default tests remain local/offline.", -``` - -Update `test_verify_delivery_package_checks` in `test_cli.py`: - -```python - self.assertIn("scripts/numina_runtime.py", [item["path"] for item in payload["files"]]) - self.assertIn("configure", payload["commands"]["available"]) -``` - -- [ ] **Step 4: Run full tests and delivery verification** - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/AI4Math-Lean-Agents/tests -``` - -Expected: all tests pass. - -Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests -``` - -Expected: JSON has `"ok": true`, `"status": "delivery_ready"`, and `"unit_tests": {"ok": true, ...}`. - -- [ ] **Step 5: Commit** - -```bash -git add README.md AGENTS.md CLAUDE.md GEMINI.md \ - skills/AI4Math-Lean-Agents/SKILL.md \ - skills/AI4Math-Lean-Agents/agents/openai.yaml \ - skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml \ - skills/AI4Math-Lean-Agents/references/numina_runtime.md \ - skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md \ - skills/AI4Math-Lean-Agents/scripts/verify_delivery.py \ - skills/AI4Math-Lean-Agents/tests/test_cli.py -git commit -m "Document official Numina runtime workflow" -``` - ---- - -## Final Verification Checklist - -- [ ] Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/AI4Math-Lean-Agents/tests -``` - -Expected: all tests pass. - -- [ ] Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests -``` - -Expected: `"ok": true` and `"status": "delivery_ready"`. - -- [ ] Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name dryrun --dry-run -``` - -Expected: JSON includes `numina_actions` and the official upstream URL. - -- [ ] Run: - -```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . -``` - -Expected: JSON includes a Numina readiness summary and no secret values. - -- [ ] Run: - -```bash -git status --short -``` - -Expected: no unstaged or uncommitted implementation changes. - ---- - -## Self-Review Notes - -- Spec coverage: The plan covers existing-skill modification, official upstream install/configure through existing CLI, runtime state, human-in-the-loop Numina invocation guidance, docs, tests, delivery verifier, and external API disclosure. -- Completeness scan: The plan uses concrete code snippets, exact commands, expected outputs, and no open-ended steps. -- Type consistency: Runtime status names use the spec vocabulary: `missing_numina_runtime`, `upstream_dirty`, `numina_run_ready`, and `direct_task_ready`. diff --git a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md b/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md deleted file mode 100644 index ae915db..0000000 --- a/docs/superpowers/specs/2026-05-24-numina-lean-agent-runtime-design.md +++ /dev/null @@ -1,336 +0,0 @@ -# AI4Math Lean Agents 调用原版 Numina 改造设计 - -## 背景 - -当前 `AI4Math-Lean-Agents` skill 的定位是“蒸馏版”直接 Lean coding-agent 工作流:Codex 自己读写 Lean,CLI 只做确定性 guardrail,并且文档明确写着不部署、不调用 Numina。 - -用户现在希望保留这个 skill 的总框架,但把定位改成:**自动抓取官方原版 Numina Lean Agent,在本地交互配置环境,然后调用上游 Numina runner**。直接 Lean 操作仍可作为诊断、review、最小失败 handoff 和 fallback,但不再是唯一主路径。 - -## 目标 - -改造现有 `skills/AI4Math-Lean-Agents/`,不新增 sister skill。 - -改造后,这个 skill 必须支持: - -- clone 或更新官方 `project-numina/numina-lean-agent`; -- 本地配置 Numina 运行环境、Python 依赖、Claude CLI/API key 和相关 skill keys; -- 为用户的 Lean/Lake 项目调用官方 Numina runner; -- 在调用前检查工具、credential、Lake 项目结构和上游 checkout 状态; -- 保留现有 Lean/Lake 校验、patch review、`sorry` 检测、最小失败提取等 guardrails; -- 明确告诉用户:默认证明/修复路线会调用原版 Numina,可能产生外部 API 调用和费用。 - -## 非目标 - -- 不创建新的 `Numina-Lean-Agent-Runtime/` skill 目录。 -- 默认不 vendor、不 fork、不修改 Numina 源码。 -- 不把密钥写入 git 跟踪文件。 -- 不假装离线、无 key、无外部 API 可完成 Numina 路线。 -- 不删除现有直接 Lean 工具;它们继续服务于检查、review、fallback 和失败最小化。 - -## 保持不大动的现有框架 - -继续使用现有包: - -```text -skills/ - AI4Math-Lean-Agents/ - SKILL.md - agents/ - openai.yaml - config/ - prompts/ - references/ - schemas/ - scripts/ - tests/ -``` - -在现有框架内新增: - -```text -skills/AI4Math-Lean-Agents/ - config/ - numina_runtime.example.toml - references/ - numina_runtime.md - scripts/ - numina_runtime.py - tests/ - test_numina_runtime.py -``` - -并更新: - -```text -skills/AI4Math-Lean-Agents/ - SKILL.md - agents/openai.yaml - scripts/ai4m_lean.py - scripts/verify_delivery.py - README.md - AGENTS.md - CLAUDE.md - GEMINI.md -``` - -## 运行状态目录 - -Numina runtime 状态默认放在 `.ai4math/numina-runtime/`,必须被 `.ai4math/.gitignore` 忽略。 - -```text -.ai4math/ - numina-runtime/ - upstream/ # 官方 project-numina/numina-lean-agent clone - projects/ # setup.sh 可用的本地项目工作区 - results/ # wrapper 默认结果目录 - .env.local # 可选本地环境变量覆盖,不跟踪 - numina_runtime.local.toml -``` - -wrapper 必须支持: - -- `AI4MATH_NUMINA_HOME`:覆盖 runtime 根目录。 -- `NUMINA_LEAN_AGENT_REPO`:仅在用户明确要求时覆盖上游仓库 URL。 -- `NUMINA_LEAN_AGENT_REF`:可选 branch、tag 或 commit。 - -默认上游 URL 固定为: - -```text -https://github.com/project-numina/numina-lean-agent -``` - -## CLI 设计 - -继续用 `scripts/ai4m_lean.py` 作为总入口,但不增加一组平行的 `numina-*` 公开命令。Numina 部署和调用应该折叠进现有命令: - -```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py repair --cwd . --file /path/to/Foo.lean --dry-run -``` - -底层实现放在 `scripts/numina_runtime.py`,但这些函数是内部实现细节。`ai4m_lean.py` 只公开少量现有入口:`doctor` 展示 Numina readiness,`configure --setup-numina` 执行安装/配置,证明修复类任务继续可作为 task envelope 或 dry-run 辅助。是否调用官方 Numina,应由 coding agent 根据 `SKILL.md`、用户确认和当前项目状态决定。 - -## 现有命令语义调整 - -### 保持原样的 guardrail 命令 - -这些命令继续是本地确定性工具,不调用外部 API: - -- `env` -- `doctor` -- `check` -- `review` -- `detect-sorry` -- `minimize-failure` -- `verify-delivery` - -其中 `doctor` 和 `env` 应补充 Numina runtime readiness 摘要,但不得自动 clone、安装或调用模型。 - -### 扩展 `configure` - -现有 `configure --create-workspace` 继续保留,用于 Lean workspace。 - -新增可选 Numina 配置路径: - -```bash -python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs -``` - -它等价于执行: - -1. 内部 Numina upstream install/update; -2. 内部 Numina setup/configure; -3. 按官方 README 执行 `uv python install` 和 `uv sync`。 - -### 任务调用的交互原则 - -不要把 `prove`、`formalize`、`repair`、`complete-sorries`、`batch` 改成闭合的 Numina CLI 流水线。这个 skill 的主体验应该是人机交互: - -1. coding agent 先读用户目标、Lean 项目、当前错误和本地 runtime 状态; -2. 如果需要部署或调用官方 Numina,先说明会 clone 上游、配置依赖、可能调用外部模型 API; -3. 用户同意后,coding agent 可调用 `configure --setup-numina` 或直接运行上游 `scripts.run_claude`; -4. 如果 runtime 缺失、credential 缺失或目标不在 Lake 项目内,coding agent 给出解释和下一步,而不是静默 fallback; -5. Numina runner 结束后,coding agent 再用本地 `check`、`detect-sorry`、`review`、`minimize-failure` 做交付判断。 - -现有任务命令可以继续作为 task envelope、dry-run 说明或辅助入口,但第一版不要求它们自动执行 Numina。关键能力应写在 `SKILL.md` 和 `references/numina_runtime.md`,让 coding agent 在上下文中自行决定。 - -## Numina Runtime Wrapper - -`scripts/numina_runtime.py` 需要提供可单测的纯函数。第一版不把这些函数全部暴露成公开 CLI 子命令。 - -### readiness/doctor helpers - -供 `doctor` 和 `env` 调用,输出 JSON 片段,包含: - -- `git`、`curl`、`uv`、`elan`、`lean`、`lake`、`claude`、`python` 可用性; -- 上游是否已 clone、当前 commit、是否 dirty; -- Python/uv 环境状态; -- credential 状态,必须 redacted; -- 目标路径的 Lake 项目检测结果。 - -credential 诊断区分: - -- Claude 配置:`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_BASE_URL`、`ANTHROPIC_MODEL`,或已经可用的 `claude` CLI; -- Numina skill keys:`GEMINI_API_KEY`、`OPENAI_API_KEY`、`LEAN_LEANDEX_API_KEY`、`AXLE_API_KEY`; -- required 和 optional keys。 - -readiness/doctor helpers 不得调用外部模型 API。 - -### install helpers - -clone 或更新官方 Numina: - -- 缺失时 clone; -- 已存在时 fetch; -- 配置 `NUMINA_LEAN_AGENT_REF` 时 checkout 指定 ref; -- 上游 checkout dirty 时不覆盖,返回 `upstream_dirty`。 - -第一版必须支持: - -```bash -python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run -``` - -`--dry-run` 返回将执行的 clone/fetch/checkout/setup/sync 命令,不实际执行。 - -### configure helpers - -为指定 project name 运行上游 setup: - -```bash -python scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs -``` - -行为: - -- 确保上游已安装; -- 从上游 `tutorial/` 目录运行 `setup.sh `; -- 默认在上游根目录运行 `uv python install` 和 `uv sync`; -- 支持 `--skip-sync`; -- 记录本地 metadata; -- 失败时返回 `setup_failed` 和具体 stderr/stdout 摘要。 - -### run helpers - -供 coding agent 在交互确认后调用官方 runner: - -```bash -python scripts/ai4m_lean.py repair \ - --cwd . \ - --file /path/to/Foo.lean \ - --prompt-file /path/to/prompt.md \ - --max-rounds 10 -``` - -启动前必须验证: - -- 文件存在; -- 文件在 Lake 项目内; -- prompt 或 prompt file 存在; -- 上游安装、uv 环境和 credential 状态可用。 - -实际上游命令等价于: - -```bash -uv run python -m scripts.run_claude from-folder --prompt-file --max-rounds --result-dir -``` - -### folder/batch helpers - -供 coding agent 在交互确认后调用 folder/batch 类官方 runner: - -```bash -python scripts/ai4m_lean.py batch --cwd . --folder /path/to/LeanFolder -``` - -默认 result dir 放在 `.ai4math/numina-runtime/results/`。 - -## Skill 文档改造 - -`SKILL.md` 需要从“Numina 不部署不调用”改成: - -- 默认工作流是官方 Numina runtime assisted workflow; -- Codex 先用本地 guardrails 识别目标、检查 Lake 项目、检查 runtime; -- runtime 未安装时,引导 `configure --setup-numina --project-name ...`; -- runtime ready 时调用官方 Numina runner; -- runner 结束后用 `check`、`detect-sorry`、`review` 做交付前验证; -- 如果 Numina 路线失败,使用 `minimize-failure` 给出最小失败片段和下一步。 - -`references/numina_reverse_analysis.md` 可以保留,但应改为历史/背景材料,不再承担“只蒸馏不调用”的政策含义。 - -## 安全和本地文件 - -被 git 跟踪的文件只能包含 example config。 - -本地文件必须忽略: - -```text -.ai4math/numina-runtime/ -``` - -wrapper 必须读取 `.ai4math/numina-runtime/.env.local`(如果存在),但输出 redacted 状态,不打印真实 secret。除非用户明确要求,不写入用户密钥。 - -## 错误状态 - -新增或使用这些 status: - -- `numina_ready` -- `missing_numina_runtime` -- `missing_numina_credentials` -- `missing_lake_project` -- `upstream_dirty` -- `numina_setup_failed` -- `numina_run_failed` -- `direct_task_ready` - -`ai4m_lean.py` 需要把 Numina 相关失败映射到稳定 exit code,避免和 Lean 编译失败混淆。 - -## 测试 - -默认测试必须离线、确定性、无 API。 - -新增单测覆盖: - -- Numina runtime 默认路径解析; -- `.ai4math/.gitignore` 写入 `numina-runtime/`; -- Lake project root detection 复用现有逻辑; -- `configure --setup-numina --dry-run` 使用官方上游 URL; -- dirty upstream 保护; -- credential redaction; -- `configure --setup-numina --dry-run` 构造官方 Numina install/setup command plan; -- task commands 继续保留旧 direct task envelope,不被强制改造成 Numina 流水线; -- `SKILL.md` 明确列出 coding agent 何时应调用 Numina、何时应停下来问用户。 -- `verify-delivery` 检查新增文件和命令。 - -默认测试不得: - -- clone 官方仓库; -- 运行 `uv sync`; -- 调用 `claude`; -- 调用外部 API。 - -可选集成测试用环境变量门控: - -```text -AI4MATH_NUMINA_INTEGRATION=1 -``` - -## 验收标准 - -实现完成时必须满足: - -- `verify-delivery --run-tests` 通过; -- 新增 Numina runtime offline tests 通过; -- `configure --setup-numina --dry-run` 输出官方上游 URL; -- `doctor` 在未安装 runtime 的 fresh checkout 上清楚报告下一步; -- `SKILL.md`、README、AGENTS/CLAUDE/GEMINI 说明一致:本 skill 现在会部署并调用官方 Numina; -- 最终交付仍拒绝 `sorry`、`admit` 和新 `axiom`。 - -## 实现决策 - -- 不新增 sister skill,直接改造 `AI4Math-Lean-Agents`。 -- 保留现有 direct Lean guardrails 和任务 envelope。 -- Numina 部署和调用作为 skill 的交互式主能力,不做成大量公开 CLI。 -- 第一版必须支持 `configure --setup-numina --dry-run`,降低真实部署风险。 -- 默认 runtime 根目录是 `.ai4math/numina-runtime/`。 diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index 9343470..72f066f 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -9,7 +9,7 @@ Use this skill when the user wants Lean 4 formalization, proof repair, theorem t The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake commands, and repository context. Use helper commands only when their deterministic output is useful. -Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under ignored local state at `.ai4math/numina-runtime/`; the coding agent explains clone, setup, API-key, and Claude Code implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. +Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under ignored local state at `.ai4math/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. ## Agent Playbook @@ -40,7 +40,7 @@ All helper commands emit machine-readable JSON on stdout. Human-readable diagnos ## Numina Runtime -When using the official Numina runtime, follow `references/numina_runtime.md`. The helper code only plans, installs, and reports readiness; proof strategy remains a conversation between the user, the coding agent, local Lean checks, and, when approved, the official Numina runner. +When using the official Numina runtime, follow `references/numina_runtime.md`. The helper code only plans, installs, and reports readiness; proof strategy remains a human-in-the-loop process with the user, the coding agent, local Lean checks, and, when approved, the official Numina runner. ## Safety Rules From 0716be02add123fb57ce49a5355201f42e4f60a5 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 25 May 2026 00:07:35 +0800 Subject: [PATCH 11/37] Refine skill interaction defaults --- .codex/skills/ai4math-lean-agents/SKILL.md | 14 ------ .cursor/rules/ai4math-lean-agents.mdc | 2 +- .opencode/agents/ai4math-lean-agents.md | 1 + AGENTS.md | 3 +- CLAUDE.md | 2 + GEMINI.md | 2 + README.md | 10 ++-- skills/AI4Math-Lean-Agents/SKILL.md | 27 +++++----- skills/AI4Math-Lean-Agents/agents/openai.yaml | 2 +- skills/AI4Math-Lean-Agents/config/env.example | 5 +- .../config/lean_agent.example.toml | 4 +- .../config/numina_runtime.example.toml | 2 +- .../references/direct_lean_workflow.md | 2 +- .../references/lean_runtime_configuration.md | 18 +++---- .../references/numina_reverse_analysis.md | 4 +- .../references/numina_runtime.md | 12 ++--- skills/AI4Math-Lean-Agents/scripts/common.py | 23 ++++++--- .../scripts/configure_lean.py | 11 ++-- .../scripts/direct_task.py | 8 +-- .../scripts/numina_runtime.py | 6 +-- skills/AI4Math-Lean-Agents/tests/test_cli.py | 7 ++- .../tests/test_common_config.py | 12 ++++- .../tests/test_configure_lean.py | 18 +++++-- .../tests/test_direct_task.py | 8 ++- .../tests/test_numina_runtime.py | 50 +++++++++++++------ 25 files changed, 152 insertions(+), 101 deletions(-) delete mode 100644 .codex/skills/ai4math-lean-agents/SKILL.md diff --git a/.codex/skills/ai4math-lean-agents/SKILL.md b/.codex/skills/ai4math-lean-agents/SKILL.md deleted file mode 100644 index 55af262..0000000 --- a/.codex/skills/ai4math-lean-agents/SKILL.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: ai4math-lean-agents -description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, optional official Numina runtime deployment/calls, theorem formalization, sorry completion, patch review, and minimal failure handoff. ---- - -# AI4Math Lean Agents Repo Shim - -This repo-local shim points to the canonical skill: - -```text -../../../skills/AI4Math-Lean-Agents/SKILL.md -``` - -Read that file and follow it as the source of truth. The coding agent should directly operate Lean; helper CLI commands are guardrails, not a proof backend. Numina is optional and should be used only through the canonical human-in-the-loop runtime flow. diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index fbafe5f..a794dda 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -The coding agent directly edits Lean and validates with Lean/Lake. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index a4dd6d9..4cb73e4 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -11,6 +11,7 @@ skills/AI4Math-Lean-Agents/SKILL.md Rules: - Directly inspect and edit Lean files. +- Match the user's language by default. - Validate with Lean/Lake after meaningful edits. - Use helper CLI commands only as deterministic guardrails. - Use official Numina only through the approved human-in-the-loop runtime flow. diff --git a/AGENTS.md b/AGENTS.md index 232f78e..ee91304 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,8 @@ Core rules: - The coding agent directly operates Lean; do not treat helper CLI commands as a proof backend. - Numina is optional: deploy or call the official runtime only through the human-in-the-loop flow in `references/numina_runtime.md`. -- Prefer the user's existing Lake project. Use `.ai4math/lean-workspace` only when a standalone file needs project context. +- Match the user's language by default. +- Prefer the user's existing Lake project. Use the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` only when a standalone file needs project context. - Preserve theorem statements unless the user explicitly approves a change. - Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. - Do not commit API keys, local runtime state, or machine-specific Numina paths. diff --git a/CLAUDE.md b/CLAUDE.md index 8a3cd67..313347e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,4 +8,6 @@ skills/AI4Math-Lean-Agents/SKILL.md Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run Lean/Lake checks frequently, and use the helper CLI only for deterministic checks such as environment inspection, optional Numina readiness/setup, patch review, `sorry` detection, and minimal failure extraction. +Match the user's language by default. + Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index 637cda0..fefa0a3 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -8,4 +8,6 @@ skills/AI4Math-Lean-Agents/SKILL.md The agent should directly inspect and edit Lean files, validate with Lean/Lake, preserve theorem statements, and avoid final patches with `sorry`, `admit`, or new `axiom`. +Match the user's language by default. + The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. It can report and configure the official Numina runtime when the user explicitly wants that path, but the agent should still validate final Lean patches locally. diff --git a/README.md b/README.md index 609f208..5fd8930 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,13 @@ skills/AI4Math-Lean-Agents/ ## What It Supports - Lean project/workspace inspection. -- Reusable `.ai4math/lean-workspace` setup for standalone Lean files. +- Reusable shared `~/.ai4math/lean-workspace` setup for standalone Lean files. - Theorem formalization, proof repair, proof completion, and `sorry` completion. - Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. - Minimal failing Lean fragment extraction when a proof is blocked. - Optional official `project-numina/numina-lean-agent` deployment/call flow, mediated by the coding agent. -Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `.ai4math/numina-runtime/`. +Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `~/.ai4math/numina-runtime/` by default. ## Repository Layout @@ -29,7 +29,6 @@ Numina is optional. The public CLI does not expose a parallel `numina-*` workflo ├── README.md ├── LICENSE ├── .github/ -├── .codex/ # optional Codex adapter ├── .cursor/ # optional Cursor rule ├── .opencode/ # optional OpenCode agent └── skills/ @@ -55,12 +54,11 @@ skills/AI4Math-Lean-Agents/SKILL.md The repository also includes lightweight adapters for several agent environments: - `AGENTS.md` for general repository-aware coding agents. -- `.codex/skills/ai4math-lean-agents/SKILL.md` as a Codex repo-local shim. - `.cursor/rules/ai4math-lean-agents.mdc` for Cursor. - `.opencode/agents/ai4math-lean-agents.md` for OpenCode. - `CLAUDE.md` and `GEMINI.md` for agent-specific repository instructions. -For Codex-style skill installation, sync the skill folder into the user skill directory: +For Codex-style skill installation, sync the skill folder into the user skill directory. The repository does not include a repo-local Codex shim, so a workspace that also has the system skill installed will not show two `ai4math-lean-agents` entries. ```bash mkdir -p ~/.codex/skills @@ -82,7 +80,7 @@ python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py check --cwd . --skip-buil python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` -The helper CLI is not the proof engine. The coding agent remains responsible for reading Lean errors, editing proofs, and choosing proof strategy. +The helper CLI is not the proof engine. The coding agent remains responsible for reading Lean errors, editing proofs, choosing proof strategy, and matching the user's language. For the optional Numina path, read `skills/AI4Math-Lean-Agents/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index 72f066f..e66d86d 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -7,29 +7,32 @@ description: Use for interactive Lean 4 formal verification with reusable Lean/m Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or an official Numina Lean Agent run. The active coding agent is the Lean agent: it asks clarifying questions, reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, and iterates with the user. +Match the user's language by default. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. + The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake commands, and repository context. Use helper commands only when their deterministic output is useful. -Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under ignored local state at `.ai4math/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. +Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. ## Agent Playbook 1. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. 2. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available. -3. For standalone files, use or create `.ai4math/lean-workspace` only when a project context is needed. -4. If the user asks for original Numina behavior, or if an official Numina run would clearly help, inspect `doctor` readiness, explain the deployment/call, and proceed only after approval. -5. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -6. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. -7. Preserve theorem statements unless the user explicitly approves a change. -8. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. -9. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. +3. For standalone files, use or create the shared workspace `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`; do not create a second project-local workspace unless the user asks for isolation. +4. When reporting readiness, separate direct Lean readiness from optional Numina readiness. Do not describe the environment as "not configured" when a Lake project or shared Lean workspace is already usable. +5. If the user asks for original Numina behavior, or if an official Numina run would clearly help, inspect `doctor` readiness, explain the deployment/call, and proceed only after approval. +6. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. +7. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. +8. Preserve theorem statements unless the user explicitly approves a change. +9. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. +10. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. ## Helper Toolbox Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk: - `env` / `doctor`: inspect Lean workspace, local tool availability, and optional Numina readiness. -- `configure --create-workspace`: create or reuse the managed workspace. -- `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `.ai4math/numina-runtime/`. +- `configure --create-workspace`: create or reuse the shared managed workspace. +- `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`. - `check`: run a structured Lean/Lake validation. - `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. - `minimize-failure`: extract a compact failing Lean fragment. @@ -44,10 +47,10 @@ When using the official Numina runtime, follow `references/numina_runtime.md`. T ## Safety Rules -- Do not require Numina, Claude Code CLI, external model APIs, or API keys unless the user explicitly wants an official Numina deployment or run. +- Do not require Numina, Claude CLI tooling, external model APIs, or API keys unless the user explicitly wants an official Numina deployment or run. - Do not commit local machine-specific paths. - Do not call external APIs during `env`, `doctor`, `check`, `review`, `detect-sorry`, tests, or dry-runs. -- Do not store secrets in tracked files; use environment variables or `.ai4math/numina-runtime/.env.local`. +- Do not store secrets in tracked files; use environment variables or `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/.env.local`. - Do not accept final Lean patches containing `sorry`, `admit`, or newly introduced `axiom`. - Do not silently weaken theorem statements or change existing project versions. - Do not let helper command availability override a better direct coding-agent path. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index abb0523..59e010f 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents short_description: Interactive Lean 4 verification with reusable mathlib workspaces and optional official Numina runtime setup. -default_prompt: Use the Lean agent playbook to formalize, prove, repair, review, or minimize this Lean task. Use helper CLI checks only when useful; use official Numina only through the approved human-in-the-loop runtime flow. +default_prompt: Use the Lean agent playbook to formalize, prove, repair, review, or minimize this Lean task. Match the user's language. Use the shared AI4Math workspace for standalone files, helper CLI checks only when useful, and official Numina only through the approved human-in-the-loop runtime flow. diff --git a/skills/AI4Math-Lean-Agents/config/env.example b/skills/AI4Math-Lean-Agents/config/env.example index 3524a47..64fe72f 100644 --- a/skills/AI4Math-Lean-Agents/config/env.example +++ b/skills/AI4Math-Lean-Agents/config/env.example @@ -1,4 +1,5 @@ # Copy values into an ignored local file or export them manually. -export AI4MATH_LEAN_WORKSPACE=".ai4math/lean-workspace" +export AI4MATH_HOME="~/.ai4math" +export AI4MATH_LEAN_WORKSPACE="~/.ai4math/lean-workspace" export AI4MATH_LEAN_TOOLCHAIN="leanprover/lean4:v4.28.0" -export AI4MATH_NUMINA_HOME=".ai4math/numina-runtime" +export AI4MATH_NUMINA_HOME="~/.ai4math/numina-runtime" diff --git a/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml b/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml index 0d6ef5a..c862ff8 100644 --- a/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml +++ b/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml @@ -3,8 +3,8 @@ default_cwd = "." validate_command = "lake build" single_file_check_template = "lake env lean {file}" workspace_mode = "reuse-managed" -managed_workspace_path = ".ai4math/lean-workspace" -managed_workspace_root = ".ai4math/lean-workspaces" +managed_workspace_path = "~/.ai4math/lean-workspace" +managed_workspace_root = "~/.ai4math/lean-workspaces" managed_workspace_template = "math" reuse_managed_workspace = true workspace_key = "lean-toolchain" diff --git a/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml b/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml index d3600c2..180ef04 100644 --- a/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml +++ b/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml @@ -1,6 +1,6 @@ [numina] upstream_url = "https://github.com/project-numina/numina-lean-agent" -runtime_home = ".ai4math/numina-runtime" +runtime_home = "~/.ai4math/numina-runtime" default_project_name = "myproofs" default_prompt_file = "prompts/autosearch/main_entry.md" default_max_rounds = 10 diff --git a/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md b/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md index aff3445..f2b9dbb 100644 --- a/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md +++ b/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md @@ -29,7 +29,7 @@ Do not route creative proof search through helper commands. `prove`, `formalize` ## Workspace Choice -Prefer a user's existing Lake project when the target file is inside one. For standalone `.lean` files, use the reusable `.ai4math/lean-workspace` so Lean, Lake, and mathlib artifacts are shared across tasks. +Prefer a user's existing Lake project when the target file is inside one. For standalone `.lean` files, use the reusable `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` so Lean, Lake, and mathlib artifacts are shared across tasks and projects. When a user project has its own `lean-toolchain` and mathlib revision, keep those versions unless the user explicitly approves a change. When creating a managed workspace, use the configured preferred toolchain or `auto`. diff --git a/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md b/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md index d62a20f..da803e5 100644 --- a/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md +++ b/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md @@ -2,19 +2,18 @@ This skill uses a direct coding-agent workflow by default. It can also prepare an optional official Numina runtime under ignored local state when the user approves that path; see `numina_runtime.md` for deployment and call details. -## Local Layout +## Shared Layout ```text -.ai4math/ +${AI4MATH_HOME:-~/.ai4math}/ ├── lean-workspace/ ├── lean-workspaces/ ├── numina-runtime/ -├── lean_agent.local.toml ├── logs/ └── failures/ ``` -The skill should create `.ai4math/.gitignore` before writing local config. +Repository-local machine settings still live under `/.ai4math/` and should not be committed. The reusable Lean workspace and optional Numina runtime are shared by default so standalone tasks do not create a fresh workspace in every project. ## Tool Checks @@ -29,7 +28,7 @@ Required local tools for the direct workflow are `git`, `python3`, `elan`, `lean ## Reusable Lean Workspace -For standalone tasks, prefer `.ai4math/lean-workspace`. Create it once with: +For standalone tasks, prefer `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. Create it once with: ```bash python scripts/ai4m_lean.py configure --cwd . --create-workspace --toolchain leanprover/lean4:v4.28.0 @@ -44,7 +43,7 @@ lake exe cache get lake build ``` -If a user project already has `lean-toolchain` and `lakefile.{lean,toml}`, use that project and do not change versions without approval. If a standalone task needs a different Lean/mathlib revision than the managed workspace, use a versioned workspace under `.ai4math/lean-workspaces/`. +If a user project already has `lean-toolchain` and `lakefile.{lean,toml}`, use that project and do not change versions without approval. If a standalone task needs a different Lean/mathlib revision than the shared managed workspace, use a versioned workspace under `${AI4MATH_HOME:-~/.ai4math}/lean-workspaces/`. ## Local Config @@ -53,7 +52,7 @@ Machine-specific settings live in `.ai4math/lean_agent.local.toml` and should no ```toml [lean] workspace_mode = "reuse-managed" -managed_workspace_path = ".ai4math/lean-workspace" +managed_workspace_path = "~/.ai4math/lean-workspace" align_workspace_versions = true preferred_toolchain = "auto" @@ -65,7 +64,8 @@ backend = "none" Environment overrides: ```bash -export AI4MATH_LEAN_WORKSPACE=".ai4math/lean-workspace" +export AI4MATH_HOME="~/.ai4math" +export AI4MATH_LEAN_WORKSPACE="~/.ai4math/lean-workspace" export AI4MATH_LEAN_TOOLCHAIN="leanprover/lean4:v4.28.0" -export AI4MATH_NUMINA_HOME=".ai4math/numina-runtime" +export AI4MATH_NUMINA_HOME="~/.ai4math/numina-runtime" ``` diff --git a/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md b/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md index 14b523b..1b8071b 100644 --- a/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md +++ b/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md @@ -31,7 +31,7 @@ The default AI4Math loop still works without these runtime dependencies: - API-key or login setup; - backend round streaming or benchmark execution. -When the user wants original Numina behavior, those concerns are handled by the official upstream checkout under `.ai4math/numina-runtime/` and the human-in-the-loop flow in `numina_runtime.md`. +When the user wants original Numina behavior, those concerns are handled by the official upstream checkout under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/` and the human-in-the-loop flow in `numina_runtime.md`. ## Adapted Direct Workflow @@ -58,7 +58,7 @@ flowchart TD | Statement drift guard | `validate_patch.py` | | Placeholder guard | `detect_sorry.py` and `review` | | Minimal blocked artifact | `extract_minimal_failure.py` | -| Reusable project context | `.ai4math/lean-workspace` | +| Reusable project context | `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` | ## Failure Lessons diff --git a/skills/AI4Math-Lean-Agents/references/numina_runtime.md b/skills/AI4Math-Lean-Agents/references/numina_runtime.md index 2cf0bb3..edc09d6 100644 --- a/skills/AI4Math-Lean-Agents/references/numina_runtime.md +++ b/skills/AI4Math-Lean-Agents/references/numina_runtime.md @@ -8,21 +8,21 @@ This skill can deploy and call the official `project-numina/numina-lean-agent` r 2. Run `doctor --cwd .` when useful and read the `numina` readiness block. 3. Explain what setup may do: clone the official repository, run `tutorial/setup.sh`, install or use `elan`, `lake`, `curl`, `uv`, and `claude`, and require model/API credentials for some tools. 4. After approval, run `configure --cwd . --setup-numina --project-name `. Use `--dry-run` first when the user wants to review commands. -5. For an official run, call the upstream runner from `.ai4math/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. +5. For an official run, call the upstream runner from `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. 6. After Numina changes Lean files, use local `check`, `detect-sorry`, and `review` before accepting the patch. ## Local State -- Runtime root: `.ai4math/numina-runtime/` -- Upstream checkout: `.ai4math/numina-runtime/upstream/` -- Ignored credential file: `.ai4math/numina-runtime/.env.local` -- Suggested outputs: `.ai4math/numina-runtime/results/` +- Runtime root: `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/` +- Upstream checkout: `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream/` +- Ignored credential file: `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/.env.local` +- Suggested outputs: `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/results/` Do not commit runtime state, API keys, generated results, or local machine paths. ## Credentials -Claude Code authentication can come from the user's normal Claude login or environment variables such as `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`. Numina's CLI skills may also need `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, or `AXLE_API_KEY`. +Claude authentication can come from the user's normal Claude CLI login or environment variables such as `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`. Numina's CLI skills may also need `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, or `AXLE_API_KEY`. The helper readiness report redacts values and only reports whether keys appear configured. diff --git a/skills/AI4Math-Lean-Agents/scripts/common.py b/skills/AI4Math-Lean-Agents/scripts/common.py index 778db24..addc80f 100644 --- a/skills/AI4Math-Lean-Agents/scripts/common.py +++ b/skills/AI4Math-Lean-Agents/scripts/common.py @@ -86,6 +86,14 @@ def expand_path(value: str | None, cwd: Path) -> Path | None: return Path(os.path.abspath(path)) +def ai4math_home(cwd: str | Path = ".") -> Path: + cwd_path = Path(cwd).resolve() + override = os.environ.get("AI4MATH_HOME") + if override: + return expand_path(override, cwd_path) or (Path.home() / ".ai4math") + return Path.home() / ".ai4math" + + def read_config(cwd: str | Path = ".", config_path: str | Path | None = None) -> dict[str, Any]: cwd_path = Path(cwd).resolve() config = load_toml(DEFAULT_CONFIG) @@ -94,14 +102,15 @@ def read_config(cwd: str | Path = ".", config_path: str | Path | None = None) -> local_config = cwd_path / ".ai4math" / "lean_agent.local.toml" config = deep_merge(config, load_toml(local_config)) - env_lean = { - key: value - for key, value in { - "managed_workspace_path": os.environ.get("AI4MATH_LEAN_WORKSPACE"), - "preferred_toolchain": os.environ.get("AI4MATH_LEAN_TOOLCHAIN"), - }.items() - if value + home = ai4math_home(cwd_path) + env_values = { + "managed_workspace_path": os.environ.get("AI4MATH_LEAN_WORKSPACE"), + "preferred_toolchain": os.environ.get("AI4MATH_LEAN_TOOLCHAIN"), } + if os.environ.get("AI4MATH_HOME") and not env_values["managed_workspace_path"]: + env_values["managed_workspace_path"] = str(home / "lean-workspace") + env_values["managed_workspace_root"] = str(home / "lean-workspaces") + env_lean = {key: value for key, value in env_values.items() if value} if env_lean: config = deep_merge(config, {"lean": env_lean}) return config diff --git a/skills/AI4Math-Lean-Agents/scripts/configure_lean.py b/skills/AI4Math-Lean-Agents/scripts/configure_lean.py index 24f91c3..16a5dd7 100644 --- a/skills/AI4Math-Lean-Agents/scripts/configure_lean.py +++ b/skills/AI4Math-Lean-Agents/scripts/configure_lean.py @@ -5,7 +5,7 @@ from typing import Any from check_lean_project import find_project_root, read_mathlib_revision, read_toolchain -from common import ensure_ai4math_gitignore, expand_path, read_config, run_command, update_local_toml +from common import ai4math_home, ensure_ai4math_gitignore, expand_path, read_config, run_command, update_local_toml from numina_runtime import execute_configure_plan, numina_readiness from tool_status import find_tool @@ -57,14 +57,14 @@ def inspect_environment(cwd: str | Path = ".", config_path: str | Path | None = lean = config.get("lean", {}) target_path = Path(target).expanduser().resolve() if target else cwd_path project_root = find_project_root(target_path) - workspace_path = expand_path(lean.get("managed_workspace_path"), cwd_path) or (cwd_path / ".ai4math" / "lean-workspace") + workspace_path = expand_path(lean.get("managed_workspace_path"), cwd_path) or (ai4math_home(cwd_path) / "lean-workspace") workspace_root = find_project_root(workspace_path) if workspace_path.exists() else None missing: list[str] = [] required_inputs: list[str] = [] if project_root is None and workspace_root is None: missing.append("lean_workspace") - required_inputs.append("existing Lake project or permission to create reusable .ai4math/lean-workspace") + required_inputs.append("existing Lake project or permission to create/reuse the shared Lean workspace") return { "ok": not missing, @@ -113,7 +113,8 @@ def configure( config = read_config(cwd_path, config_path) lean = config.get("lean", {}) - workspace = expand_path(lean.get("managed_workspace_path"), cwd_path) or (cwd_path / ".ai4math" / "lean-workspace") + workspace = expand_path(lean.get("managed_workspace_path"), cwd_path) or (ai4math_home(cwd_path) / "lean-workspace") + workspace_root_config = expand_path(lean.get("managed_workspace_root"), cwd_path) or (workspace.parent / "lean-workspaces") workspace_actions: list[dict[str, Any]] = [] if create_workspace: lake = find_tool("lake") or "lake" @@ -165,7 +166,7 @@ def configure( "lean": { "workspace_mode": "reuse-managed", "managed_workspace_path": str(workspace), - "managed_workspace_root": str(cwd_path / ".ai4math" / "lean-workspaces"), + "managed_workspace_root": str(workspace_root_config), "reuse_managed_workspace": True, "workspace_key": "lean-toolchain", "align_workspace_versions": True, diff --git a/skills/AI4Math-Lean-Agents/scripts/direct_task.py b/skills/AI4Math-Lean-Agents/scripts/direct_task.py index 6350c04..db80b63 100644 --- a/skills/AI4Math-Lean-Agents/scripts/direct_task.py +++ b/skills/AI4Math-Lean-Agents/scripts/direct_task.py @@ -4,7 +4,7 @@ from typing import Any from check_lean_project import find_project_root, read_mathlib_revision, read_toolchain -from common import expand_path, read_config +from common import ai4math_home, expand_path, read_config TASK_TO_PROMPT = { @@ -18,7 +18,7 @@ def _managed_workspace_root(config: dict[str, Any], cwd_path: Path) -> tuple[Path | None, Path]: lean = config.get("lean", {}) - workspace_path = expand_path(lean.get("managed_workspace_path"), cwd_path) or (cwd_path / ".ai4math" / "lean-workspace") + workspace_path = expand_path(lean.get("managed_workspace_path"), cwd_path) or (ai4math_home(cwd_path) / "lean-workspace") workspace_root = find_project_root(workspace_path) if workspace_path.exists() else None return workspace_root, workspace_path @@ -78,8 +78,8 @@ def build_direct_task( "result_dir": str(Path(result_dir).expanduser().resolve()) if result_dir else None, "max_rounds": max_rounds, "missing_config": missing, - "required_inputs": ["existing Lake project or reusable managed workspace"] if "lean_workspace" in missing else [], - "recommended_next_action": "run configure --create-workspace or move target into a Lake project" if missing else "coding agent should edit/check directly", + "required_inputs": ["existing Lake project or shared reusable managed workspace"] if "lean_workspace" in missing else [], + "recommended_next_action": "run configure --create-workspace for the shared workspace or move target into a Lake project" if missing else "coding agent should edit/check directly", "direct_workflow": next_actions, } diff --git a/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py b/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py index 740fbcc..9e984fc 100644 --- a/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py +++ b/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any -from common import ENV_KEY_RE, ensure_ai4math_gitignore, expand_path, run_command +from common import ENV_KEY_RE, ai4math_home, ensure_ai4math_gitignore, expand_path, run_command from tool_status import tool_versions @@ -19,8 +19,8 @@ def runtime_root(cwd: str | Path) -> Path: cwd_path = Path(cwd).resolve() override = os.environ.get("AI4MATH_NUMINA_HOME") if override: - return expand_path(override, cwd_path) or (cwd_path / ".ai4math" / "numina-runtime") - return cwd_path / ".ai4math" / "numina-runtime" + return expand_path(override, cwd_path) or (ai4math_home(cwd_path) / "numina-runtime") + return ai4math_home(cwd_path) / "numina-runtime" def runtime_paths(cwd: str | Path) -> dict[str, str]: diff --git a/skills/AI4Math-Lean-Agents/tests/test_cli.py b/skills/AI4Math-Lean-Agents/tests/test_cli.py index 804d8c5..f18d0a0 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_cli.py +++ b/skills/AI4Math-Lean-Agents/tests/test_cli.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import os import subprocess import sys import tempfile @@ -41,6 +42,7 @@ def test_dry_run_prove_outputs_direct_task(self) -> None: text=True, capture_output=True, check=False, + env={**os.environ, "AI4MATH_LEAN_WORKSPACE": str(workspace), "AI4MATH_NUMINA_HOME": str(root / "shared-ai4math" / "numina-runtime")}, ) self.assertEqual(result.returncode, 0, result.stderr) payload = json.loads(result.stdout) @@ -72,6 +74,7 @@ def test_doctor_outputs_tool_report(self) -> None: text=True, capture_output=True, check=False, + env={**os.environ, "AI4MATH_HOME": str(SKILL_ROOT / ".test-ai4math-home"), "AI4MATH_NUMINA_HOME": ""}, ) self.assertEqual(result.returncode, 0, result.stderr) payload = json.loads(result.stdout) @@ -83,13 +86,14 @@ def test_doctor_outputs_tool_report(self) -> None: def test_configure_setup_numina_dry_run_outputs_official_upstream(self) -> None: with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) result = subprocess.run( [ sys.executable, str(CLI), "configure", "--cwd", - tmp, + str(root), "--setup-numina", "--project-name", "demo_project", @@ -98,6 +102,7 @@ def test_configure_setup_numina_dry_run_outputs_official_upstream(self) -> None: text=True, capture_output=True, check=False, + env={**os.environ, "AI4MATH_HOME": str(root / "shared-ai4math"), "AI4MATH_NUMINA_HOME": ""}, ) self.assertEqual(result.returncode, 0, result.stderr) payload = json.loads(result.stdout) diff --git a/skills/AI4Math-Lean-Agents/tests/test_common_config.py b/skills/AI4Math-Lean-Agents/tests/test_common_config.py index b1951b5..7637370 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_common_config.py +++ b/skills/AI4Math-Lean-Agents/tests/test_common_config.py @@ -9,7 +9,7 @@ SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" sys.path.insert(0, str(SCRIPTS)) -from common import expand_path, load_toml, read_env_local, write_env_local # noqa: E402 +from common import ai4math_home, expand_path, load_toml, read_env_local, write_env_local # noqa: E402 class CommonConfigTests(unittest.TestCase): @@ -37,6 +37,16 @@ def test_expand_path_preserves_symlink_text(self) -> None: self.assertEqual(expand_path(str(link), root), link) + def test_ai4math_home_honors_environment_override(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + custom = root / "shared-ai4math" + + with patch.dict("os.environ", {"AI4MATH_HOME": str(custom)}, clear=False): + result = ai4math_home(root) + + self.assertEqual(result, custom) + def test_write_env_local_updates_values_and_is_ignored(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) diff --git a/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py b/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py index b8d87ff..26fdf2f 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py +++ b/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py @@ -3,6 +3,7 @@ import sys import tempfile import unittest +import os from pathlib import Path from unittest.mock import patch @@ -22,7 +23,9 @@ def test_existing_lean_project_is_direct_agent_ready(self) -> None: (root / "lakefile.toml").write_text('name = "proj"\n', encoding="utf-8") target.write_text("example : True := by trivial\n", encoding="utf-8") - result = inspect_environment(root, target=target) + with patch.dict(os.environ, {"AI4MATH_HOME": str(root / "shared-ai4math")}, clear=False): + os.environ["AI4MATH_LEAN_WORKSPACE"] = "" + result = inspect_environment(root, target=target) self.assertTrue(result["ok"]) self.assertEqual(result["agent"]["mode"], "direct-coding-agent") @@ -36,7 +39,9 @@ def test_save_local_writes_lean_agent_config(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) - result = configure(root, save_local=True, toolchain="leanprover/lean4:v4.28.0") + with patch.dict(os.environ, {"AI4MATH_HOME": str(root / "shared-ai4math")}, clear=False): + os.environ["AI4MATH_LEAN_WORKSPACE"] = "" + result = configure(root, save_local=True, toolchain="leanprover/lean4:v4.28.0") local = load_toml(root / ".ai4math" / "lean_agent.local.toml") self.assertFalse(result["ok"]) @@ -50,7 +55,8 @@ def test_workspace_creation_failure_is_reported_as_lean_setup_failure(self) -> N with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) - with patch("configure_lean.find_tool", return_value="/usr/bin/lake"), \ + with patch.dict(os.environ, {"AI4MATH_HOME": str(root / "shared-ai4math")}, clear=False), \ + patch("configure_lean.find_tool", return_value="/usr/bin/lake"), \ patch("configure_lean.run_command", return_value={ "ok": False, "returncode": 1, @@ -58,6 +64,7 @@ def test_workspace_creation_failure_is_reported_as_lean_setup_failure(self) -> N "stderr": "download failed", "command": ["/usr/bin/lake", "new", "lean_workspace", "math"], }): + os.environ["AI4MATH_LEAN_WORKSPACE"] = "" result = configure(root, create_workspace=True) self.assertFalse(result["ok"]) @@ -66,7 +73,10 @@ def test_workspace_creation_failure_is_reported_as_lean_setup_failure(self) -> N def test_configure_setup_numina_requires_project_name(self) -> None: with tempfile.TemporaryDirectory() as tmp: - result = configure(Path(tmp), setup_numina=True, dry_run=True) + root = Path(tmp) + with patch.dict(os.environ, {"AI4MATH_HOME": str(root / "shared-ai4math")}, clear=False): + os.environ["AI4MATH_LEAN_WORKSPACE"] = "" + result = configure(root, setup_numina=True, dry_run=True) self.assertFalse(result["numina"]["ok"]) self.assertEqual(result["numina"]["status"], "missing_project_name") diff --git a/skills/AI4Math-Lean-Agents/tests/test_direct_task.py b/skills/AI4Math-Lean-Agents/tests/test_direct_task.py index b6f6363..dd5d82a 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_direct_task.py +++ b/skills/AI4Math-Lean-Agents/tests/test_direct_task.py @@ -3,7 +3,9 @@ import sys import tempfile import unittest +import os from pathlib import Path +from unittest.mock import patch SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" sys.path.insert(0, str(SCRIPTS)) @@ -22,7 +24,8 @@ def test_managed_workspace_routes_standalone_file_without_backend(self) -> None: target = root / "Standalone.lean" target.write_text("example : True := by trivial\n", encoding="utf-8") - result = build_direct_task("prove", root, target) + with patch.dict(os.environ, {"AI4MATH_LEAN_WORKSPACE": str(workspace)}, clear=False): + result = build_direct_task("prove", root, target) self.assertTrue(result["ok"]) self.assertEqual(result["status"], "direct_task_ready") @@ -37,7 +40,8 @@ def test_missing_workspace_reports_required_input(self) -> None: target = root / "Standalone.lean" target.write_text("example : True := by trivial\n", encoding="utf-8") - result = build_direct_task("prove", root, target) + with patch.dict(os.environ, {"AI4MATH_HOME": str(root / "shared-ai4math"), "AI4MATH_LEAN_WORKSPACE": ""}, clear=False): + result = build_direct_task("prove", root, target) self.assertFalse(result["ok"]) self.assertEqual(result["status"], "missing_config") diff --git a/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py b/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py index f2b828b..fd834c4 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +++ b/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py @@ -25,12 +25,16 @@ class NuminaRuntimePathTests(unittest.TestCase): def test_runtime_paths_default_under_ai4math(self) -> None: with tempfile.TemporaryDirectory() as tmp: - paths = runtime_paths(Path(tmp)) + root = Path(tmp) + shared = root / "shared-ai4math" + + with patch.dict(os.environ, {"AI4MATH_HOME": str(shared), "AI4MATH_NUMINA_HOME": ""}, clear=False): + paths = runtime_paths(root) - root = Path(tmp).resolve() / ".ai4math" / "numina-runtime" - self.assertEqual(paths["root"], str(root)) - self.assertEqual(paths["upstream"], str(root / "upstream")) - self.assertEqual(paths["results"], str(root / "results")) + runtime = shared / "numina-runtime" + self.assertEqual(paths["root"], str(runtime)) + self.assertEqual(paths["upstream"], str(runtime / "upstream")) + self.assertEqual(paths["results"], str(runtime / "results")) self.assertEqual(paths["default_upstream_url"], DEFAULT_UPSTREAM_URL) def test_runtime_paths_honor_ai4math_numina_home(self) -> None: @@ -55,7 +59,9 @@ def test_numina_runtime_is_ignored(self) -> None: class NuminaRuntimeCredentialTests(unittest.TestCase): def test_env_local_is_read_from_numina_runtime_root(self) -> None: with tempfile.TemporaryDirectory() as tmp: - env_path = Path(tmp) / ".ai4math" / "numina-runtime" / ".env.local" + root = Path(tmp) + shared = root / "shared-ai4math" + env_path = shared / "numina-runtime" / ".env.local" env_path.parent.mkdir(parents=True) env_path.write_text( "export ANTHROPIC_AUTH_TOKEN=secret-token\n" @@ -63,7 +69,8 @@ def test_env_local_is_read_from_numina_runtime_root(self) -> None: encoding="utf-8", ) - values = read_numina_env_local(Path(tmp)) + with patch.dict(os.environ, {"AI4MATH_HOME": str(shared), "AI4MATH_NUMINA_HOME": ""}, clear=False): + values = read_numina_env_local(root) self.assertEqual(values["ANTHROPIC_AUTH_TOKEN"], "secret-token") self.assertEqual(values["OPENAI_API_KEY"], "sk-test") @@ -83,7 +90,10 @@ def test_credential_report_redacts_values(self) -> None: class NuminaRuntimePlanTests(unittest.TestCase): def test_install_plan_clones_official_upstream_when_missing(self) -> None: with tempfile.TemporaryDirectory() as tmp: - plan = build_install_plan(Path(tmp), dry_run=True) + root = Path(tmp) + shared = root / "shared-ai4math" + with patch.dict(os.environ, {"AI4MATH_HOME": str(shared), "AI4MATH_NUMINA_HOME": ""}, clear=False): + plan = build_install_plan(root, dry_run=True) self.assertTrue(plan["ok"]) self.assertEqual(plan["status"], "install_plan_ready") @@ -92,18 +102,21 @@ def test_install_plan_clones_official_upstream_when_missing(self) -> None: def test_install_plan_blocks_dirty_upstream(self) -> None: with tempfile.TemporaryDirectory() as tmp: - upstream = Path(tmp) / ".ai4math" / "numina-runtime" / "upstream" + root = Path(tmp) + shared = root / "shared-ai4math" + upstream = shared / "numina-runtime" / "upstream" upstream.mkdir(parents=True) (upstream / ".git").mkdir() - with patch("numina_runtime.run_command", return_value={ + with patch.dict(os.environ, {"AI4MATH_HOME": str(shared), "AI4MATH_NUMINA_HOME": ""}, clear=False), \ + patch("numina_runtime.run_command", return_value={ "ok": True, "returncode": 0, "stdout": " M tutorial/foo.py\n", "stderr": "", "command": ["git", "status", "--short"], }): - plan = build_install_plan(Path(tmp), dry_run=False) + plan = build_install_plan(root, dry_run=False) self.assertFalse(plan["ok"]) self.assertEqual(plan["status"], "dirty_upstream") @@ -111,17 +124,20 @@ def test_install_plan_blocks_dirty_upstream(self) -> None: def test_configure_plan_uses_official_setup_and_uv_commands(self) -> None: with tempfile.TemporaryDirectory() as tmp: - upstream = Path(tmp) / ".ai4math" / "numina-runtime" / "upstream" + root = Path(tmp) + shared = root / "shared-ai4math" + upstream = shared / "numina-runtime" / "upstream" (upstream / ".git").mkdir(parents=True) - with patch("numina_runtime.run_command", return_value={ + with patch.dict(os.environ, {"AI4MATH_HOME": str(shared), "AI4MATH_NUMINA_HOME": ""}, clear=False), \ + patch("numina_runtime.run_command", return_value={ "ok": True, "returncode": 0, "stdout": "", "stderr": "", "command": ["git", "status", "--short"], }): - plan = build_configure_plan(Path(tmp), project_name="demo_project", dry_run=True) + plan = build_configure_plan(root, project_name="demo_project", dry_run=True) commands = [action["command"] for action in plan["actions"]] self.assertTrue(plan["ok"]) @@ -135,10 +151,12 @@ def test_run_plan_uses_official_runner_without_executing(self) -> None: root = Path(tmp) theorem = root / "Demo.lean" theorem.write_text("example : True := by\n trivial\n", encoding="utf-8") - upstream = root / ".ai4math" / "numina-runtime" / "upstream" + shared = root / "shared-ai4math" + upstream = shared / "numina-runtime" / "upstream" upstream.mkdir(parents=True) - plan = build_run_plan(root, file=theorem, max_iters=3) + with patch.dict(os.environ, {"AI4MATH_HOME": str(shared), "AI4MATH_NUMINA_HOME": ""}, clear=False): + plan = build_run_plan(root, file=theorem, max_iters=3) self.assertTrue(plan["ok"]) self.assertEqual(plan["status"], "run_plan_ready") From 67da901478b5be86c1b960740a68c5e6f536a98e Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 25 May 2026 00:14:14 +0800 Subject: [PATCH 12/37] Make Lean skill proactively guide sessions --- .cursor/rules/ai4math-lean-agents.mdc | 2 +- .opencode/agents/ai4math-lean-agents.md | 1 + AGENTS.md | 1 + CLAUDE.md | 1 + GEMINI.md | 1 + skills/AI4Math-Lean-Agents/SKILL.md | 25 +++++++++++-------- skills/AI4Math-Lean-Agents/agents/openai.yaml | 2 +- .../references/interactive_orchestration.md | 23 ++++++++++++++++- .../scripts/verify_delivery.py | 13 +++++++++- 9 files changed, 55 insertions(+), 14 deletions(-) diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index a794dda..914943f 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index 4cb73e4..0551681 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -12,6 +12,7 @@ Rules: - Directly inspect and edit Lean files. - Match the user's language by default. +- Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Validate with Lean/Lake after meaningful edits. - Use helper CLI commands only as deterministic guardrails. - Use official Numina only through the approved human-in-the-loop runtime flow. diff --git a/AGENTS.md b/AGENTS.md index ee91304..3b120c1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,7 @@ Core rules: - The coding agent directly operates Lean; do not treat helper CLI commands as a proof backend. - Numina is optional: deploy or call the official runtime only through the human-in-the-loop flow in `references/numina_runtime.md`. - Match the user's language by default. +- Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Prefer the user's existing Lake project. Use the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` only when a standalone file needs project context. - Preserve theorem statements unless the user explicitly approves a change. - Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. diff --git a/CLAUDE.md b/CLAUDE.md index 313347e..875fe20 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,5 +9,6 @@ skills/AI4Math-Lean-Agents/SKILL.md Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run Lean/Lake checks frequently, and use the helper CLI only for deterministic checks such as environment inspection, optional Numina readiness/setup, patch review, `sorry` detection, and minimal failure extraction. Match the user's language by default. +Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index fefa0a3..9b2c07d 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -9,5 +9,6 @@ skills/AI4Math-Lean-Agents/SKILL.md The agent should directly inspect and edit Lean files, validate with Lean/Lake, preserve theorem statements, and avoid final patches with `sorry`, `admit`, or new `axiom`. Match the user's language by default. +Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. It can report and configure the official Numina runtime when the user explicitly wants that path, but the agent should still validate final Lean patches locally. diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index e66d86d..c51fdd0 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -9,22 +9,27 @@ Use this skill when the user wants Lean 4 formalization, proof repair, theorem t Match the user's language by default. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. +Lead the interaction; do not wait for the user to drive every step. When the user's request is broad or underspecified, first orient yourself to the Lean project/workspace state, then propose the next useful action in plain language. Do not open with a passive "send me the file" checklist when you can inspect context or offer a concrete starting path. + The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake commands, and repository context. Use helper commands only when their deterministic output is useful. Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. ## Agent Playbook -1. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. -2. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available. -3. For standalone files, use or create the shared workspace `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`; do not create a second project-local workspace unless the user asks for isolation. -4. When reporting readiness, separate direct Lean readiness from optional Numina readiness. Do not describe the environment as "not configured" when a Lake project or shared Lean workspace is already usable. -5. If the user asks for original Numina behavior, or if an official Numina run would clearly help, inspect `doctor` readiness, explain the deployment/call, and proceed only after approval. -6. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -7. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. -8. Preserve theorem statements unless the user explicitly approves a change. -9. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. -10. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. +1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, and optional Numina runtime, and summarize what is already usable. +2. If the user has not provided a precise target, offer a small next-step menu such as repair an existing Lean file, formalize a natural-language/LaTeX theorem, inspect a Lean project, or prepare the shared workspace. +3. Ask at most one blocking question at a time. Prefer a concrete recommendation plus one decision question over a list of required inputs. +4. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. +5. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available. +6. For standalone files, use or create the shared workspace `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`; do not create a second project-local workspace unless the user asks for isolation. +7. When reporting readiness, separate direct Lean readiness from optional Numina readiness. Do not describe the environment as "not configured" when a Lake project or shared Lean workspace is already usable. +8. If the user asks for original Numina behavior, or if an official Numina run would clearly help, inspect `doctor` readiness, explain the deployment/call, and proceed only after approval. +9. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. +10. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. +11. Preserve theorem statements unless the user explicitly approves a change. +12. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. +13. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. ## Helper Toolbox diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index 59e010f..bded877 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents short_description: Interactive Lean 4 verification with reusable mathlib workspaces and optional official Numina runtime setup. -default_prompt: Use the Lean agent playbook to formalize, prove, repair, review, or minimize this Lean task. Match the user's language. Use the shared AI4Math workspace for standalone files, helper CLI checks only when useful, and official Numina only through the approved human-in-the-loop runtime flow. +default_prompt: Lead the Lean session proactively. Match the user's language, orient to the current Lean/Lake and shared AI4Math workspace state, recommend the next useful action, and ask at most one blocking question at a time. Use helper CLI checks only when useful and official Numina only through the approved human-in-the-loop runtime flow. diff --git a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md index 4cb0793..b27efd1 100644 --- a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md +++ b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md @@ -2,7 +2,26 @@ The coordinating coding agent owns both user interaction and proof iteration. It does not delegate proof search to Numina, helper CLI commands, or any external backend. -This reference covers the guidance layer: intake, task classification, decomposition, direct Lean editing, result review, bounded iteration, and minimal failure handoff. +This reference covers the guidance layer: session opening, intake, task classification, decomposition, direct Lean editing, result review, bounded iteration, and minimal failure handoff. + +## Session Opening + +Lead the interaction; do not wait for the user to drive every step. On a broad request, first orient to the current state instead of asking for every input at once: + +- inspect whether the current directory is a Lake project; +- check whether the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` exists; +- mention optional Numina readiness separately from direct Lean readiness; +- say what can be done immediately and what would require confirmation. + +If no precise target is provided, offer a small menu and recommend one path. For example: + +- repair or complete an existing Lean file; +- formalize a natural-language or LaTeX theorem; +- inspect a Lean/Lake project and summarize readiness; +- prepare the shared Lean workspace; +- discuss whether an official Numina run is appropriate. + +Ask at most one blocking question at a time. A good opening ends with one decision question, not a checklist. ## Intake Questions @@ -14,6 +33,8 @@ Ask only when not inferable: - Should standalone work use the reusable managed workspace? - For natural-language or LaTeX input, what statement should be considered authoritative? +Prefer asking these only after orientation. If the repository already reveals the likely next step, state the recommendation and ask for confirmation. + ## Decomposition Break large requests into small Lean targets that can be checked with direct Lean/Lake commands or the optional helper `check` command. diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py index c3c0874..2eb56fe 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py @@ -101,18 +101,29 @@ def _package_hygiene() -> dict[str, Any]: def _guidance_first_check() -> dict[str, Any]: text = (SKILL_ROOT / "SKILL.md").read_text(encoding="utf-8", errors="replace") + orchestration = (SKILL_ROOT / "references" / "interactive_orchestration.md").read_text(encoding="utf-8", errors="replace") required_phrases = [ "## Agent Playbook", "## Helper Toolbox", + "Lead the interaction; do not wait for the user to drive every step.", + "offer a small next-step menu", + "Ask at most one blocking question at a time.", "The bundled CLI is a helper toolbox, not the workflow driver.", "Use official Numina through a human-in-the-loop runtime workflow.", "Do not turn helper commands into a closed proof workflow.", "Do not let helper command availability override a better direct coding-agent path.", ] missing = [phrase for phrase in required_phrases if phrase not in text] + orchestration_required = [ + "## Session Opening", + "Lead the interaction; do not wait for the user to drive every step.", + "A good opening ends with one decision question, not a checklist.", + ] + orchestration_missing = [phrase for phrase in orchestration_required if phrase not in orchestration] return { - "ok": not missing and "## Commands" not in text, + "ok": not missing and not orchestration_missing and "## Commands" not in text, "missing_phrases": missing, + "orchestration_missing_phrases": orchestration_missing, "commands_section_present": "## Commands" in text, } From 14a22547bdb5f10a61f355c75b19a2a3ecc0f98b Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 25 May 2026 09:09:50 +0800 Subject: [PATCH 13/37] Tighten Lean skill guidance flow --- .cursor/rules/ai4math-lean-agents.mdc | 2 +- .opencode/agents/ai4math-lean-agents.md | 2 ++ AGENTS.md | 2 ++ CLAUDE.md | 2 ++ GEMINI.md | 2 ++ skills/AI4Math-Lean-Agents/SKILL.md | 6 ++++-- skills/AI4Math-Lean-Agents/agents/openai.yaml | 2 +- .../references/interactive_orchestration.md | 4 ++++ skills/AI4Math-Lean-Agents/scripts/verify_delivery.py | 6 ++++++ 9 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index 914943f..2778011 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default, without treating language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index 0551681..3eeb3f6 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -13,6 +13,8 @@ Rules: - Directly inspect and edit Lean files. - Match the user's language by default. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. +- Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. +- When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. - Validate with Lean/Lake after meaningful edits. - Use helper CLI commands only as deterministic guardrails. - Use official Numina only through the approved human-in-the-loop runtime flow. diff --git a/AGENTS.md b/AGENTS.md index 3b120c1..3ab7566 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,6 +8,8 @@ Core rules: - Numina is optional: deploy or call the official runtime only through the human-in-the-loop flow in `references/numina_runtime.md`. - Match the user's language by default. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. +- Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. +- When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. - Prefer the user's existing Lake project. Use the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` only when a standalone file needs project context. - Preserve theorem statements unless the user explicitly approves a change. - Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. diff --git a/CLAUDE.md b/CLAUDE.md index 875fe20..1846e4b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,5 +10,7 @@ Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run L Match the user's language by default. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. +Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. +When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index 9b2c07d..a394960 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -10,5 +10,7 @@ The agent should directly inspect and edit Lean files, validate with Lean/Lake, Match the user's language by default. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. +Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. +When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. It can report and configure the official Numina runtime when the user explicitly wants that path, but the agent should still validate final Lean patches locally. diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index c51fdd0..b892d52 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -7,10 +7,12 @@ description: Use for interactive Lean 4 formal verification with reusable Lean/m Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or an official Numina Lean Agent run. The active coding agent is the Lean agent: it asks clarifying questions, reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, and iterates with the user. -Match the user's language by default. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. +Match the user's language by default. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. A language switch is not a task reset. Keep the current environment state, prior diagnosis, and recommended next action, then continue leading in the new language. Lead the interaction; do not wait for the user to drive every step. When the user's request is broad or underspecified, first orient yourself to the Lean project/workspace state, then propose the next useful action in plain language. Do not open with a passive "send me the file" checklist when you can inspect context or offer a concrete starting path. +If no target is available, run or propose a safe local smoke/readiness check. Then recommend a default path, such as validating the current Lake project, preparing the shared workspace, or formalizing a small sample theorem. Avoid ending with only "send me a file" or an equivalent passive handoff. + The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake commands, and repository context. Use helper commands only when their deterministic output is useful. Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. @@ -18,7 +20,7 @@ Use official Numina through a human-in-the-loop runtime workflow. Numina is opti ## Agent Playbook 1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, and optional Numina runtime, and summarize what is already usable. -2. If the user has not provided a precise target, offer a small next-step menu such as repair an existing Lean file, formalize a natural-language/LaTeX theorem, inspect a Lean project, or prepare the shared workspace. +2. If the user has not provided a precise target, offer a small next-step menu such as repair an existing Lean file, formalize a natural-language/LaTeX theorem, inspect a Lean project, or prepare the shared workspace. Recommend one default path based on what inspection found. 3. Ask at most one blocking question at a time. Prefer a concrete recommendation plus one decision question over a list of required inputs. 4. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. 5. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index bded877..2d44134 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents short_description: Interactive Lean 4 verification with reusable mathlib workspaces and optional official Numina runtime setup. -default_prompt: Lead the Lean session proactively. Match the user's language, orient to the current Lean/Lake and shared AI4Math workspace state, recommend the next useful action, and ask at most one blocking question at a time. Use helper CLI checks only when useful and official Numina only through the approved human-in-the-loop runtime flow. +default_prompt: Lead the Lean session proactively. Match the user's language without treating language switches as task resets, orient to the current Lean/Lake and shared AI4Math workspace state, run or propose a safe readiness check when no target is provided, recommend the next useful action, and ask at most one blocking question at a time. Use helper CLI checks only when useful and official Numina only through the approved human-in-the-loop runtime flow. diff --git a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md index b27efd1..9131668 100644 --- a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md +++ b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md @@ -13,6 +13,10 @@ Lead the interaction; do not wait for the user to drive every step. On a broad r - mention optional Numina readiness separately from direct Lean readiness; - say what can be done immediately and what would require confirmation. +A language switch is not a task reset. Restate the current state in the user's language, keep the prior diagnosis, and continue with the recommended next action instead of returning to generic intake. + +If no target is available, run or propose a safe local smoke/readiness check. Good examples are `lake env lean` against the shared workspace, `lake build` for the user's current Lake project when it is already present, or a helper `doctor` check when environment status is the question. Avoid ending with only "send me a file" or an equivalent passive handoff. + If no precise target is provided, offer a small menu and recommend one path. For example: - repair or complete an existing Lean file; diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py index 2eb56fe..8359f45 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py @@ -106,6 +106,9 @@ def _guidance_first_check() -> dict[str, Any]: "## Agent Playbook", "## Helper Toolbox", "Lead the interaction; do not wait for the user to drive every step.", + "A language switch is not a task reset.", + "If no target is available, run or propose a safe local smoke/readiness check.", + "Avoid ending with only \"send me a file\"", "offer a small next-step menu", "Ask at most one blocking question at a time.", "The bundled CLI is a helper toolbox, not the workflow driver.", @@ -117,6 +120,9 @@ def _guidance_first_check() -> dict[str, Any]: orchestration_required = [ "## Session Opening", "Lead the interaction; do not wait for the user to drive every step.", + "A language switch is not a task reset.", + "If no target is available, run or propose a safe local smoke/readiness check.", + "Avoid ending with only \"send me a file\"", "A good opening ends with one decision question, not a checklist.", ] orchestration_missing = [phrase for phrase in orchestration_required if phrase not in orchestration] From c8f0cf9dbea6b3becd51818c436cd233c39f2455 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 25 May 2026 10:39:55 +0800 Subject: [PATCH 14/37] Require Numina readiness in Lean skill opening --- .cursor/rules/ai4math-lean-agents.mdc | 2 +- .opencode/agents/ai4math-lean-agents.md | 2 ++ AGENTS.md | 2 ++ CLAUDE.md | 2 ++ GEMINI.md | 2 ++ skills/AI4Math-Lean-Agents/SKILL.md | 4 +++- skills/AI4Math-Lean-Agents/agents/openai.yaml | 2 +- .../references/interactive_orchestration.md | 4 ++++ skills/AI4Math-Lean-Agents/references/numina_runtime.md | 2 ++ skills/AI4Math-Lean-Agents/scripts/verify_delivery.py | 6 ++++++ 10 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index 2778011..3a0482e 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default, without treating language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default, without treating language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index 3eeb3f6..c71e75f 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -15,6 +15,8 @@ Rules: - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +- Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +- Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. - Validate with Lean/Lake after meaningful edits. - Use helper CLI commands only as deterministic guardrails. - Use official Numina only through the approved human-in-the-loop runtime flow. diff --git a/AGENTS.md b/AGENTS.md index 3ab7566..6ba9f2a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,6 +10,8 @@ Core rules: - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +- Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +- Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. - Prefer the user's existing Lake project. Use the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` only when a standalone file needs project context. - Preserve theorem statements unless the user explicitly approves a change. - Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. diff --git a/CLAUDE.md b/CLAUDE.md index 1846e4b..8dc6e80 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,5 +12,7 @@ Match the user's language by default. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index a394960..0746bd4 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -12,5 +12,7 @@ Match the user's language by default. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. It can report and configure the official Numina runtime when the user explicitly wants that path, but the agent should still validate final Lean patches locally. diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index b892d52..b8f0f45 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -17,9 +17,11 @@ The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal codi Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. +Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Do not say Numina is unnecessary before checking or explaining its readiness. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. + ## Agent Playbook -1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, and optional Numina runtime, and summarize what is already usable. +1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, and optional Numina runtime, and summarize what is already usable. Treat upstream Numina example projects as demos only; do not let their pinned `lean-toolchain` make the shared workspace look broken. 2. If the user has not provided a precise target, offer a small next-step menu such as repair an existing Lean file, formalize a natural-language/LaTeX theorem, inspect a Lean project, or prepare the shared workspace. Recommend one default path based on what inspection found. 3. Ask at most one blocking question at a time. Prefer a concrete recommendation plus one decision question over a list of required inputs. 4. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index 2d44134..0bf7110 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents short_description: Interactive Lean 4 verification with reusable mathlib workspaces and optional official Numina runtime setup. -default_prompt: Lead the Lean session proactively. Match the user's language without treating language switches as task resets, orient to the current Lean/Lake and shared AI4Math workspace state, run or propose a safe readiness check when no target is provided, recommend the next useful action, and ask at most one blocking question at a time. Use helper CLI checks only when useful and official Numina only through the approved human-in-the-loop runtime flow. +default_prompt: Lead the Lean session proactively. Match the user's language from the first visible response, and if recent context is Chinese, answer in Chinese. Do not treat language switches as task resets. Inspect direct Lean, shared workspace, and optional Numina readiness before recommending work. Prefer the shared Lean workspace for user tasks; upstream Numina examples are demos and may pin different toolchains. Ask at most one blocking question at a time. Use helper CLI checks only when useful and official Numina only through the approved human-in-the-loop runtime flow. diff --git a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md index 9131668..55c79ab 100644 --- a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md +++ b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md @@ -13,6 +13,10 @@ Lead the interaction; do not wait for the user to drive every step. On a broad r - mention optional Numina readiness separately from direct Lean readiness; - say what can be done immediately and what would require confirmation. +Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Do not say Numina is unnecessary before checking or explaining its readiness. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. + +When checking Numina, distinguish runtime readiness from upstream demo readiness. The runtime can be usable with the shared Lean workspace even if an upstream example or benchmark pins a different `lean-toolchain`. Report that as an example-project issue, not as a failure of the shared environment. + A language switch is not a task reset. Restate the current state in the user's language, keep the prior diagnosis, and continue with the recommended next action instead of returning to generic intake. If no target is available, run or propose a safe local smoke/readiness check. Good examples are `lake env lean` against the shared workspace, `lake build` for the user's current Lake project when it is already present, or a helper `doctor` check when environment status is the question. Avoid ending with only "send me a file" or an equivalent passive handoff. diff --git a/skills/AI4Math-Lean-Agents/references/numina_runtime.md b/skills/AI4Math-Lean-Agents/references/numina_runtime.md index edc09d6..9dd8321 100644 --- a/skills/AI4Math-Lean-Agents/references/numina_runtime.md +++ b/skills/AI4Math-Lean-Agents/references/numina_runtime.md @@ -11,6 +11,8 @@ This skill can deploy and call the official `project-numina/numina-lean-agent` r 5. For an official run, call the upstream runner from `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. 6. After Numina changes Lean files, use local `check`, `detect-sorry`, and `review` before accepting the patch. +Default to the shared Lean workspace for user tasks. Upstream Numina examples or benchmarks may pin their own `lean-toolchain`; that only describes the example project, not the readiness of `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. + ## Local State - Runtime root: `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/` diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py index 8359f45..472d66d 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py @@ -109,6 +109,9 @@ def _guidance_first_check() -> dict[str, Any]: "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", + "Opening readiness should inspect both direct Lean and optional Numina status before recommending work.", + "Do not say Numina is unnecessary before checking or explaining its readiness.", + "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "offer a small next-step menu", "Ask at most one blocking question at a time.", "The bundled CLI is a helper toolbox, not the workflow driver.", @@ -123,6 +126,9 @@ def _guidance_first_check() -> dict[str, Any]: "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", + "Opening readiness should inspect both direct Lean and optional Numina status before recommending work.", + "Do not say Numina is unnecessary before checking or explaining its readiness.", + "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "A good opening ends with one decision question, not a checklist.", ] orchestration_missing = [phrase for phrase in orchestration_required if phrase not in orchestration] From f57b3adec3ad0607033b221566f1996b2a4f8351 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 25 May 2026 12:10:45 +0800 Subject: [PATCH 15/37] Default Lean skill startup to Chinese when ambiguous --- .cursor/rules/ai4math-lean-agents.mdc | 2 +- .opencode/agents/ai4math-lean-agents.md | 2 +- AGENTS.md | 1 + CLAUDE.md | 2 +- GEMINI.md | 2 +- skills/AI4Math-Lean-Agents/SKILL.md | 2 +- skills/AI4Math-Lean-Agents/agents/openai.yaml | 2 +- .../references/interactive_orchestration.md | 2 ++ skills/AI4Math-Lean-Agents/scripts/verify_delivery.py | 10 +++++++++- 9 files changed, 18 insertions(+), 7 deletions(-) diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index 3a0482e..2efccce 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default, without treating language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index c71e75f..d58732b 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -11,7 +11,7 @@ skills/AI4Math-Lean-Agents/SKILL.md Rules: - Directly inspect and edit Lean files. -- Match the user's language by default. +- Match the user's language by default. If the user's language is ambiguous, default to Chinese. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. diff --git a/AGENTS.md b/AGENTS.md index 6ba9f2a..931e692 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,7 @@ Core rules: - The coding agent directly operates Lean; do not treat helper CLI commands as a proof backend. - Numina is optional: deploy or call the official runtime only through the human-in-the-loop flow in `references/numina_runtime.md`. - Match the user's language by default. +- If the user's language is ambiguous, default to Chinese. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. diff --git a/CLAUDE.md b/CLAUDE.md index 8dc6e80..48e1208 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ skills/AI4Math-Lean-Agents/SKILL.md Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run Lean/Lake checks frequently, and use the helper CLI only for deterministic checks such as environment inspection, optional Numina readiness/setup, patch review, `sorry` detection, and minimal failure extraction. -Match the user's language by default. +Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. diff --git a/GEMINI.md b/GEMINI.md index 0746bd4..3dbb3f3 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -8,7 +8,7 @@ skills/AI4Math-Lean-Agents/SKILL.md The agent should directly inspect and edit Lean files, validate with Lean/Lake, preserve theorem statements, and avoid final patches with `sorry`, `admit`, or new `axiom`. -Match the user's language by default. +Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index b8f0f45..c47dc54 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -7,7 +7,7 @@ description: Use for interactive Lean 4 formal verification with reusable Lean/m Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or an official Numina Lean Agent run. The active coding agent is the Lean agent: it asks clarifying questions, reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, and iterates with the user. -Match the user's language by default. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. A language switch is not a task reset. Keep the current environment state, prior diagnosis, and recommended next action, then continue leading in the new language. +Match the user's language by default. If the user's language is ambiguous, default to Chinese. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. A language switch is not a task reset. Keep the current environment state, prior diagnosis, and recommended next action, then continue leading in the new language. Lead the interaction; do not wait for the user to drive every step. When the user's request is broad or underspecified, first orient yourself to the Lean project/workspace state, then propose the next useful action in plain language. Do not open with a passive "send me the file" checklist when you can inspect context or offer a concrete starting path. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index 0bf7110..f39e024 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents short_description: Interactive Lean 4 verification with reusable mathlib workspaces and optional official Numina runtime setup. -default_prompt: Lead the Lean session proactively. Match the user's language from the first visible response, and if recent context is Chinese, answer in Chinese. Do not treat language switches as task resets. Inspect direct Lean, shared workspace, and optional Numina readiness before recommending work. Prefer the shared Lean workspace for user tasks; upstream Numina examples are demos and may pin different toolchains. Ask at most one blocking question at a time. Use helper CLI checks only when useful and official Numina only through the approved human-in-the-loop runtime flow. +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。不要因为 skill 名称、仓库名或命令名是英文就用英文开场。不要把语言切换当成任务重置。先检查 direct Lean、共享 workspace 和可选 Numina readiness,再推荐下一步。用户任务默认使用共享 Lean workspace;upstream Numina 示例只是 demo,可能 pin 不同 toolchain。一次最多问一个阻塞问题。helper CLI 只在有用时作为检查工具;official Numina 只能走已说明并获批的人机协作 runtime 流程。 diff --git a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md index 55c79ab..a0cdf40 100644 --- a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md +++ b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md @@ -6,6 +6,8 @@ This reference covers the guidance layer: session opening, intake, task classifi ## Session Opening +If the user's language is ambiguous, default to Chinese. The skill display name, repository name, or command name is not enough evidence to choose English. + Lead the interaction; do not wait for the user to drive every step. On a broad request, first orient to the current state instead of asking for every input at once: - inspect whether the current directory is a Lake project; diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py index 472d66d..041324f 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py @@ -106,6 +106,7 @@ def _guidance_first_check() -> dict[str, Any]: "## Agent Playbook", "## Helper Toolbox", "Lead the interaction; do not wait for the user to drive every step.", + "If the user's language is ambiguous, default to Chinese.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", @@ -132,10 +133,17 @@ def _guidance_first_check() -> dict[str, Any]: "A good opening ends with one decision question, not a checklist.", ] orchestration_missing = [phrase for phrase in orchestration_required if phrase not in orchestration] + openai_yaml = (SKILL_ROOT / "agents" / "openai.yaml").read_text(encoding="utf-8", errors="replace") + openai_required = [ + "请用中文开始", + "如果用户明确使用其他语言", + ] + openai_missing = [phrase for phrase in openai_required if phrase not in openai_yaml] return { - "ok": not missing and not orchestration_missing and "## Commands" not in text, + "ok": not missing and not orchestration_missing and not openai_missing and "## Commands" not in text, "missing_phrases": missing, "orchestration_missing_phrases": orchestration_missing, + "openai_yaml_missing_phrases": openai_missing, "commands_section_present": "## Commands" in text, } From 333c8709bdcf29ead317d1c304836709769fa8d1 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 25 May 2026 12:26:37 +0800 Subject: [PATCH 16/37] Make Numina the default Lean Agent --- .cursor/rules/ai4math-lean-agents.mdc | 2 +- .opencode/agents/ai4math-lean-agents.md | 11 +++-- AGENTS.md | 10 +++-- CLAUDE.md | 7 +-- GEMINI.md | 7 +-- skills/AI4Math-Lean-Agents/SKILL.md | 43 +++++++++++-------- skills/AI4Math-Lean-Agents/agents/openai.yaml | 4 +- .../config/lean_agent.example.toml | 4 +- .../references/direct_lean_workflow.md | 10 ++--- .../references/interactive_orchestration.md | 31 ++++++++----- .../references/lean_runtime_configuration.md | 10 ++--- .../references/numina_reverse_analysis.md | 34 +++++++-------- .../references/numina_runtime.md | 14 +++--- .../schemas/result.schema.json | 1 + .../schemas/task.schema.json | 4 +- .../AI4Math-Lean-Agents/scripts/ai4m_lean.py | 8 ++-- .../scripts/configure_lean.py | 12 +++--- .../scripts/direct_task.py | 16 ++++--- .../scripts/tool_status.py | 2 +- .../scripts/verify_delivery.py | 18 +++++--- skills/AI4Math-Lean-Agents/tests/test_cli.py | 8 ++-- .../tests/test_common_config.py | 4 +- .../tests/test_configure_lean.py | 12 +++--- .../tests/test_direct_task.py | 12 +++--- 24 files changed, 159 insertions(+), 125 deletions(-) diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index 2efccce..d7f18c6 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -The coding agent directly edits Lean and validates with Lean/Lake. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation; direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index d58732b..4f3a3d3 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -1,6 +1,6 @@ # AI4Math Lean Agents -Use this agent for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, optional official Numina runtime deployment/calls, and minimal failure handoff. +Use this agent for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. Canonical workflow: @@ -10,14 +10,17 @@ skills/AI4Math-Lean-Agents/SKILL.md Rules: -- Directly inspect and edit Lean files. +- In this skill, Lean Agent means the official Numina Lean Agent runtime. +- Orchestrate Numina deployment, configuration, invocation, and local Lean validation. +- Use direct Lean editing as validation or fallback, not as the default Lean Agent mode. - Match the user's language by default. If the user's language is ambiguous, default to Chinese. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. -- Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +- Opening readiness should inspect Numina readiness before recommending work. +- Do not say API keys are unnecessary until the Numina mode is clear. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. - Validate with Lean/Lake after meaningful edits. - Use helper CLI commands only as deterministic guardrails. -- Use official Numina only through the approved human-in-the-loop runtime flow. +- Use official Numina through the approved human-in-the-loop runtime flow. - Preserve theorem statements unless the user explicitly approves a change. diff --git a/AGENTS.md b/AGENTS.md index 931e692..a6aec21 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,17 +1,19 @@ # Agent Instructions -Use the canonical skill at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, optional official Numina runtime deployment/calls, and minimal failure handoff. +Use the canonical skill at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. Core rules: -- The coding agent directly operates Lean; do not treat helper CLI commands as a proof backend. -- Numina is optional: deploy or call the official runtime only through the human-in-the-loop flow in `references/numina_runtime.md`. +- In this skill, Lean Agent means the official Numina Lean Agent runtime. +- The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation. +- Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. - Match the user's language by default. - If the user's language is ambiguous, default to Chinese. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. -- Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +- Opening readiness should inspect Numina readiness before recommending work. +- Do not say API keys are unnecessary until the Numina mode is clear. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. - Prefer the user's existing Lake project. Use the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` only when a standalone file needs project context. - Preserve theorem statements unless the user explicitly approves a change. diff --git a/CLAUDE.md b/CLAUDE.md index 48e1208..54cb5b6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,13 +6,14 @@ For Lean work in this repository, read and follow: skills/AI4Math-Lean-Agents/SKILL.md ``` -Use Claude Code as the direct Lean coding agent. Edit Lean files directly, run Lean/Lake checks frequently, and use the helper CLI only for deterministic checks such as environment inspection, optional Numina readiness/setup, patch review, `sorry` detection, and minimal failure extraction. +Use Claude Code as the Numina orchestrator and local Lean validator. In this skill, Lean Agent means the official Numina Lean Agent runtime. Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. -Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +Opening readiness should inspect Numina readiness before recommending work. +Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. +Deploy or call the official Numina runtime only after explanation and approval. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index 3dbb3f3..685bef8 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -6,13 +6,14 @@ For Lean 4 formal verification tasks, use the skill instructions at: skills/AI4Math-Lean-Agents/SKILL.md ``` -The agent should directly inspect and edit Lean files, validate with Lean/Lake, preserve theorem statements, and avoid final patches with `sorry`, `admit`, or new `axiom`. +In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation. Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. -Opening readiness should inspect both direct Lean and optional Numina status before recommending work. +Opening readiness should inspect Numina readiness before recommending work. +Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling, not an external proof backend. It can report and configure the official Numina runtime when the user explicitly wants that path, but the agent should still validate final Lean patches locally. +The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling. It can report and configure the official Numina runtime, but the agent should still validate final Lean patches locally. diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index c47dc54..0849d56 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -1,36 +1,40 @@ --- name: ai4math-lean-agents -description: Use for interactive Lean 4 formal verification with reusable Lean/mathlib workspaces, direct coding-agent proof repair, optional official Numina runtime deployment/calls, theorem formalization, sorry completion, patch review, and minimal failure handoff. +description: Use for interactive Lean 4 formal verification through the official Numina Lean Agent runtime, reusable Lean/mathlib workspaces, Numina deployment/calls, theorem formalization, proof repair, sorry completion, patch review, and minimal failure handoff. --- # AI4Math Lean Agents -Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or an official Numina Lean Agent run. The active coding agent is the Lean agent: it asks clarifying questions, reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, and iterates with the user. +Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or a Lean Agent run. + +In this skill, Lean Agent means the official Numina Lean Agent runtime. Default execution mode is Numina Agent mode. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation. Do not redefine Lean Agent as the coding agent. Match the user's language by default. If the user's language is ambiguous, default to Chinese. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. A language switch is not a task reset. Keep the current environment state, prior diagnosis, and recommended next action, then continue leading in the new language. Lead the interaction; do not wait for the user to drive every step. When the user's request is broad or underspecified, first orient yourself to the Lean project/workspace state, then propose the next useful action in plain language. Do not open with a passive "send me the file" checklist when you can inspect context or offer a concrete starting path. -If no target is available, run or propose a safe local smoke/readiness check. Then recommend a default path, such as validating the current Lake project, preparing the shared workspace, or formalizing a small sample theorem. Avoid ending with only "send me a file" or an equivalent passive handoff. +If no target is available, run or propose a safe local smoke/readiness check. Then recommend a default path, such as checking Numina readiness, preparing the shared workspace as Numina's target project, or running a tiny shared-workspace theorem before an official Numina call. Avoid ending with only "send me a file" or an equivalent passive handoff. + +The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, `rg`, Lean/Lake validation, repository context, and the official Numina runner. Use helper commands only when their deterministic output is useful. -The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake commands, and repository context. Use helper commands only when their deterministic output is useful. +Use official Numina through a human-in-the-loop runtime workflow. Numina lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. -Use official Numina through a human-in-the-loop runtime workflow. Numina is optional and lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. +Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Do not say Numina is unnecessary before checking or explaining its readiness. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. +Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Use it to check the shared workspace, validate Numina output, reduce failures, or continue locally only when the user declines or cannot use Numina. ## Agent Playbook -1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, and optional Numina runtime, and summarize what is already usable. Treat upstream Numina example projects as demos only; do not let their pinned `lean-toolchain` make the shared workspace look broken. -2. If the user has not provided a precise target, offer a small next-step menu such as repair an existing Lean file, formalize a natural-language/LaTeX theorem, inspect a Lean project, or prepare the shared workspace. Recommend one default path based on what inspection found. +1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, Numina runtime, and Numina credentials/auth, and summarize what is already usable. Treat upstream Numina example projects as demos only; do not let their pinned `lean-toolchain` make the shared workspace look broken. +2. If the user has not provided a precise target, offer a small next-step menu such as configure Numina credentials, run a Numina readiness check, prepare the shared workspace as a Numina target, formalize a natural-language/LaTeX theorem through Numina, repair an existing Lean file through Numina, or inspect a Lean project. Recommend one default path based on what inspection found. 3. Ask at most one blocking question at a time. Prefer a concrete recommendation plus one decision question over a list of required inputs. -4. Understand the user's intent: repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. -5. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available. +4. Understand the user's intent: configure Numina, call Numina, repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. +5. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available; otherwise use the shared workspace as Numina's target project. 6. For standalone files, use or create the shared workspace `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`; do not create a second project-local workspace unless the user asks for isolation. -7. When reporting readiness, separate direct Lean readiness from optional Numina readiness. Do not describe the environment as "not configured" when a Lake project or shared Lean workspace is already usable. -8. If the user asks for original Numina behavior, or if an official Numina run would clearly help, inspect `doctor` readiness, explain the deployment/call, and proceed only after approval. +7. When reporting readiness, lead with Numina readiness, then local Lean validation readiness. If Numina credentials are missing, say that Numina calls need configuration instead of implying the skill can proceed as the expected Lean Agent. +8. Before a Numina setup or run, inspect `doctor` readiness, explain the deployment/call, target project, prompt, result directory, credential state, and local validation plan; proceed only after approval. 9. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -10. Edit Lean directly in small steps. Run Lean/Lake validation after meaningful changes. +10. Call the official Numina runner for proof search/formalization when approved. After Numina changes Lean files, run Lean/Lake validation and patch safety checks before accepting results. 11. Preserve theorem statements unless the user explicitly approves a change. 12. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. 13. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. @@ -39,34 +43,35 @@ Opening readiness should inspect both direct Lean and optional Numina status bef Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk: -- `env` / `doctor`: inspect Lean workspace, local tool availability, and optional Numina readiness. +- `env` / `doctor`: inspect Lean workspace, local tool availability, and Numina readiness. - `configure --create-workspace`: create or reuse the shared managed workspace. - `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`. - `check`: run a structured Lean/Lake validation. - `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. - `minimize-failure`: extract a compact failing Lean fragment. -- `prove` / `formalize` / `repair` / `complete-sorries` / `batch`: optional dry-run task envelopes for bookkeeping; do not treat them as required proof engines. +- `prove` / `formalize` / `repair` / `complete-sorries` / `batch`: optional dry-run task envelopes for bookkeeping; prefer the official Numina runner for actual Lean Agent proof search. - `verify-delivery`: validate this skill package. All helper commands emit machine-readable JSON on stdout. Human-readable diagnostics go to stderr or log files. ## Numina Runtime -When using the official Numina runtime, follow `references/numina_runtime.md`. The helper code only plans, installs, and reports readiness; proof strategy remains a human-in-the-loop process with the user, the coding agent, local Lean checks, and, when approved, the official Numina runner. +When using the official Numina runtime, follow `references/numina_runtime.md`. Proof strategy is a human-in-the-loop process with the user, the coding agent, local Lean checks, and the official Numina runner as the default Lean Agent. ## Safety Rules -- Do not require Numina, Claude CLI tooling, external model APIs, or API keys unless the user explicitly wants an official Numina deployment or run. +- Do not call external model APIs or mutate Numina runtime state without approval. +- If the user asks for the Lean Agent, treat that as Numina and explain any needed credentials/setup directly. - Do not commit local machine-specific paths. - Do not call external APIs during `env`, `doctor`, `check`, `review`, `detect-sorry`, tests, or dry-runs. - Do not store secrets in tracked files; use environment variables or `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/.env.local`. - Do not accept final Lean patches containing `sorry`, `admit`, or newly introduced `axiom`. - Do not silently weaken theorem statements or change existing project versions. -- Do not let helper command availability override a better direct coding-agent path. +- Do not let helper command availability override the official Numina Agent path when the user expects Lean Agent behavior. ## References -- Read `references/direct_lean_workflow.md` for the full guidance-first proof/repair/formalization loop. +- Read `references/direct_lean_workflow.md` for local Lean validation and fallback repair guidance. - Read `references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. - Read `references/numina_runtime.md` when the user wants the official Numina deployment/call path. - Read `references/interactive_orchestration.md` when guiding user intake and task decomposition. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index f39e024..91eaecc 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents -short_description: Interactive Lean 4 verification with reusable mathlib workspaces and optional official Numina runtime setup. -default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。不要因为 skill 名称、仓库名或命令名是英文就用英文开场。不要把语言切换当成任务重置。先检查 direct Lean、共享 workspace 和可选 Numina readiness,再推荐下一步。用户任务默认使用共享 Lean workspace;upstream Numina 示例只是 demo,可能 pin 不同 toolchain。一次最多问一个阻塞问题。helper CLI 只在有用时作为检查工具;official Numina 只能走已说明并获批的人机协作 runtime 流程。 +short_description: Interactive Lean 4 verification through the official Numina Lean Agent runtime with reusable mathlib workspaces. +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。Lean Agent 默认指 Numina 官方 Lean Agent runtime,不要把 coding agent 重新定义成 Lean Agent。先检查 Numina readiness、共享 workspace、Claude/API 凭据和本地 Lean 验收能力,再推荐下一步。不要在 Numina 模式明确前说 API key 不需要。用户任务默认使用共享 Lean workspace;upstream Numina 示例只是 demo,可能 pin 不同 toolchain。一次最多问一个阻塞问题。coding agent 负责部署、配置、调用 Numina,并用本地 Lean/Lake 验收结果;direct Lean 只是验证或 fallback。 diff --git a/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml b/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml index c862ff8..0b28a7d 100644 --- a/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml +++ b/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml @@ -14,8 +14,8 @@ preferred_mathlib_rev = "auto" allow_user_project_version_changes = false [agent] -mode = "direct-coding-agent" -backend = "none" +mode = "numina-agent" +backend = "official-numina" max_local_iterations = 5 require_user_statement_confirmation = true diff --git a/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md b/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md index f2b9dbb..0107a63 100644 --- a/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md +++ b/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md @@ -1,15 +1,15 @@ -# Direct Lean Coding-Agent Workflow +# Local Lean Validation and Fallback Workflow -This skill distills the useful workflow pattern from Numina without deploying or calling Numina. The active coding agent is the Lean proof worker; helper CLI commands are optional guardrails. +Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. The default Lean Agent is the official Numina runtime; the coding agent uses local Lean/Lake to prepare targets, validate Numina output, minimize failures, and continue locally only when the user declines or cannot use Numina. ## Guidance-First Loop -1. Read the user's request and classify the mathematical task. +1. Read the user's request and classify whether this is Numina setup, Numina call, output validation, or fallback local repair. 2. Inspect the target files, imports, nearby lemmas, and current Lean errors. 3. Choose the validation context: existing Lake project first, managed workspace only for standalone files. 4. For formalization, draft the Lean declaration and ask for confirmation before long proof work. 5. Make one small Lean edit at a time. -6. Run direct Lean/Lake validation after meaningful edits, usually `lake env lean `, `lake build`, or the helper `check` command. +6. Run Lean/Lake validation after meaningful edits or Numina output, usually `lake env lean `, `lake build`, or the helper `check` command. 7. Diagnose the first concrete Lean error or unsolved goal before changing strategy. 8. Add helper lemmas only when they reduce proof complexity and keep theorem statements unchanged. 9. Review the final patch with direct inspection and, when useful, `review` or `detect-sorry`. @@ -25,7 +25,7 @@ Use helpers for mechanical checks: - failure handoff: `minimize-failure`; - package QA: `verify-delivery`. -Do not route creative proof search through helper commands. `prove`, `formalize`, `repair`, `complete-sorries`, and `batch` only produce optional task envelopes for bookkeeping; they are not proof engines and should not constrain how the coding agent edits Lean. +Do not route creative proof search through helper commands. `prove`, `formalize`, `repair`, `complete-sorries`, and `batch` only produce optional task envelopes for bookkeeping; the official Numina runner is the default Lean Agent for proof search/formalization. ## Workspace Choice diff --git a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md index a0cdf40..bae068e 100644 --- a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md +++ b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md @@ -1,21 +1,24 @@ # Interactive Orchestration -The coordinating coding agent owns both user interaction and proof iteration. It does not delegate proof search to Numina, helper CLI commands, or any external backend. +The coordinating coding agent owns user interaction, Numina orchestration, and final validation. It delegates proof search/formalization to the official Numina Lean Agent by default when the user asks for the Lean Agent. -This reference covers the guidance layer: session opening, intake, task classification, decomposition, direct Lean editing, result review, bounded iteration, and minimal failure handoff. +This reference covers the guidance layer: session opening, intake, task classification, Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. ## Session Opening If the user's language is ambiguous, default to Chinese. The skill display name, repository name, or command name is not enough evidence to choose English. +In this skill, Lean Agent means the official Numina Lean Agent runtime. Default execution mode is Numina Agent mode. Do not redefine Lean Agent as the coding agent. + Lead the interaction; do not wait for the user to drive every step. On a broad request, first orient to the current state instead of asking for every input at once: - inspect whether the current directory is a Lake project; - check whether the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` exists; -- mention optional Numina readiness separately from direct Lean readiness; +- inspect Numina runtime, upstream checkout, tools, and credential/auth readiness; +- mention local Lean readiness as the validation layer; - say what can be done immediately and what would require confirmation. -Opening readiness should inspect both direct Lean and optional Numina status before recommending work. Do not say Numina is unnecessary before checking or explaining its readiness. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. +Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. When checking Numina, distinguish runtime readiness from upstream demo readiness. The runtime can be usable with the shared Lean workspace even if an upstream example or benchmark pins a different `lean-toolchain`. Report that as an example-project issue, not as a failure of the shared environment. @@ -25,11 +28,11 @@ If no target is available, run or propose a safe local smoke/readiness check. Go If no precise target is provided, offer a small menu and recommend one path. For example: -- repair or complete an existing Lean file; -- formalize a natural-language or LaTeX theorem; -- inspect a Lean/Lake project and summarize readiness; -- prepare the shared Lean workspace; -- discuss whether an official Numina run is appropriate. +- configure missing Numina credentials/auth; +- run a Numina readiness check; +- prepare the shared workspace as the Numina target project; +- call Numina on a natural-language/LaTeX theorem or Lean file; +- inspect a Lean/Lake project and summarize whether Numina can target it. Ask at most one blocking question at a time. A good opening ends with one decision question, not a checklist. @@ -41,16 +44,23 @@ Ask only when not inferable: - What target file/folder and declaration should be used? - Is changing the theorem statement allowed? - Should standalone work use the reusable managed workspace? +- Should we configure/call Numina now, or only inspect readiness? - For natural-language or LaTeX input, what statement should be considered authoritative? Prefer asking these only after orientation. If the repository already reveals the likely next step, state the recommendation and ask for confirmation. ## Decomposition -Break large requests into small Lean targets that can be checked with direct Lean/Lake commands or the optional helper `check` command. +Break large requests into small Lean targets that Numina can run against and that can be checked afterward with Lean/Lake commands or the helper `check` command. For natural-language or LaTeX statements, draft the Lean declaration first and ask for confirmation before long proof work. Once the declaration is confirmed, treat statement preservation as a hard guardrail. +## Numina Run + +Before an official Numina call, state the target project/file, prompt file, max rounds, result directory, credential state, and validation plan. Ask for approval before any external model call or runtime mutation. + +After Numina returns, inspect changed Lean files, run local Lean/Lake validation, and reject results containing `sorry`, `admit`, new `axiom`, or unapproved theorem statement changes. + ## Iteration Policy Stop when: @@ -58,6 +68,7 @@ Stop when: - validation succeeds without `sorry`, `admit`, or new `axiom`; - max local iterations are reached; - Lean workspace setup is missing or broken; +- Numina credentials/auth are missing and the user has not approved fallback work; - the remaining error requires a human mathematical decision; - the only path forward would weaken the theorem statement without approval. diff --git a/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md b/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md index da803e5..d373c72 100644 --- a/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md +++ b/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md @@ -1,6 +1,6 @@ # Lean Runtime Configuration -This skill uses a direct coding-agent workflow by default. It can also prepare an optional official Numina runtime under ignored local state when the user approves that path; see `numina_runtime.md` for deployment and call details. +This skill uses the official Numina Lean Agent runtime by default. Local Lean/Lake is the validation layer and fallback repair path. Numina runtime state lives under ignored shared local state; see `numina_runtime.md` for deployment and call details. ## Shared Layout @@ -13,7 +13,7 @@ ${AI4MATH_HOME:-~/.ai4math}/ └── failures/ ``` -Repository-local machine settings still live under `/.ai4math/` and should not be committed. The reusable Lean workspace and optional Numina runtime are shared by default so standalone tasks do not create a fresh workspace in every project. +Repository-local machine settings still live under `/.ai4math/` and should not be committed. The reusable Lean workspace and Numina runtime are shared by default so standalone tasks do not create a fresh workspace in every project. ## Tool Checks @@ -24,7 +24,7 @@ python scripts/ai4m_lean.py doctor --cwd . python scripts/ai4m_lean.py env --cwd . ``` -Required local tools for the direct workflow are `git`, `python3`, `elan`, `lean`, and `lake`. Optional Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Numina and model API keys are not required for the direct workflow. +Required local validation tools are `git`, `python3`, `elan`, `lean`, and `lake`. Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Official Numina calls need a working Claude CLI/auth path and may need additional API keys for search/tool skills. ## Reusable Lean Workspace @@ -57,8 +57,8 @@ align_workspace_versions = true preferred_toolchain = "auto" [agent] -mode = "direct-coding-agent" -backend = "none" +mode = "numina-agent" +backend = "official-numina" ``` Environment overrides: diff --git a/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md b/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md index 1b8071b..b4d6d6f 100644 --- a/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md +++ b/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md @@ -1,6 +1,6 @@ # Numina Reverse Analysis for AI4Math -This reference records what was distilled from the public Numina Lean Agent workflow and what remains delegated to the optional official runtime. For deployment/call instructions, use `numina_runtime.md`. +This reference records how this skill delegates Lean Agent behavior to the public Numina Lean Agent workflow and keeps local Lean validation around it. For deployment/call instructions, use `numina_runtime.md`. ## Source Scope @@ -8,11 +8,11 @@ This reference records what was distilled from the public Numina Lean Agent work - Result repository: https://github.com/project-numina/Numina-Putnam2025 - Paper reference: https://arxiv.org/abs/2601.14027 -The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to extract reusable workflow patterns for direct coding-agent Lean work. +The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to call the official Numina runtime as the Lean Agent and use reusable AI4Math guardrails around setup, workspace choice, and validation. ## Distilled Patterns -1. Use a coding agent as the Lean worker, not merely as a chat layer. +1. Use Numina as the Lean Agent for proof search/formalization. 2. Keep Lean/Lake validation as the correctness oracle. 3. Treat theorem statement preservation as a first-class safety check. 4. Work in bounded rounds with a clear stopping condition. @@ -20,9 +20,9 @@ The goal is not to copy Numina prompts or reimplement Numina proof search. The g 6. When blocked, reduce the problem to the smallest useful failing Lean fragment. 7. Prefer reusable Lean workspaces so setup cost is not paid on every standalone problem. -## What Is Optional Runtime State +## Runtime State -The default AI4Math loop still works without these runtime dependencies: +The default AI4Math Lean Agent loop expects these runtime dependencies for official Numina calls: - upstream Numina repository checkout; - Numina Python environment; @@ -31,16 +31,16 @@ The default AI4Math loop still works without these runtime dependencies: - API-key or login setup; - backend round streaming or benchmark execution. -When the user wants original Numina behavior, those concerns are handled by the official upstream checkout under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/` and the human-in-the-loop flow in `numina_runtime.md`. +Those concerns are handled by the official upstream checkout under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/` and the human-in-the-loop flow in `numina_runtime.md`. Local direct Lean work remains available only as validation or fallback. -## Adapted Direct Workflow +## Numina-Orchestrated Workflow ```mermaid flowchart TD A["User asks for Lean work"] --> B["Coding agent classifies task"] - B --> C["Inspect Lean project or managed workspace"] - C --> D["Coding agent edits Lean directly"] - D --> E["Run Lean/Lake check"] + B --> C["Inspect Numina runtime and Lean target project"] + C --> D["Call official Numina runner after approval"] + D --> E["Run local Lean/Lake check"] E --> F{"Verified without unsafe placeholders?"} F -->|yes| G["Review patch and return result"] F -->|no| H{"Useful local iteration remains?"} @@ -50,10 +50,10 @@ flowchart TD ## AI4Math Skill Mapping -| Numina-inspired idea | Direct AI4Math implementation | +| Numina idea | AI4Math implementation | | --- | --- | | Environment gate before proof attempts | `env`, `doctor`, `configure`, `check` | -| Structured task envelope | `direct_task.py` and JSON schemas | +| Official runner invocation | `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` with documented Numina commands | | Bounded proof rounds | `max_local_iterations` / `max_rounds` | | Statement drift guard | `validate_patch.py` | | Placeholder guard | `detect_sorry.py` and `review` | @@ -71,10 +71,8 @@ flowchart TD If a future agent reads this file during normal Lean work, the default action item is: -1. use the direct skill CLI to verify local Lean readiness; -2. edit Lean directly; -3. run Lean/Lake checks frequently; -4. review safety constraints; +1. verify Numina runtime/auth readiness; +2. prepare the target in the user's Lake project or shared workspace; +3. explain and call the official Numina runner after approval; +4. validate resulting Lean changes locally; 5. return a verified patch or minimal failure. - -If the user asks for original Numina behavior, switch to `numina_runtime.md`, explain setup/call implications, and validate all resulting Lean changes locally. diff --git a/skills/AI4Math-Lean-Agents/references/numina_runtime.md b/skills/AI4Math-Lean-Agents/references/numina_runtime.md index 9dd8321..1def3b2 100644 --- a/skills/AI4Math-Lean-Agents/references/numina_runtime.md +++ b/skills/AI4Math-Lean-Agents/references/numina_runtime.md @@ -1,14 +1,14 @@ -# Optional Official Numina Runtime +# Official Numina Lean Agent Runtime -This skill can deploy and call the official `project-numina/numina-lean-agent` repository when the user wants the original Numina behavior. Treat it as an optional human-in-the-loop runtime, not as the default proof backend. +This skill treats the official `project-numina/numina-lean-agent` repository as the default Lean Agent. The coding agent manages setup, calls, user approvals, and final Lean validation. ## Agent Flow -1. Clarify the user's intent: direct Lean repair, official Numina run, or a mix. -2. Run `doctor --cwd .` when useful and read the `numina` readiness block. -3. Explain what setup may do: clone the official repository, run `tutorial/setup.sh`, install or use `elan`, `lake`, `curl`, `uv`, and `claude`, and require model/API credentials for some tools. +1. Clarify the target: configure Numina, call Numina on a Lean project/file/folder, or validate Numina output. +2. Run `doctor --cwd .` when useful and read the `numina` readiness block before recommending a path. +3. Explain what setup may do: clone the official repository, run `tutorial/setup.sh`, install or use `elan`, `lake`, `curl`, `uv`, and `claude`, and require model/API credentials or Claude CLI auth for calls. 4. After approval, run `configure --cwd . --setup-numina --project-name `. Use `--dry-run` first when the user wants to review commands. -5. For an official run, call the upstream runner from `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. +5. For an official Numina Agent run, call the upstream runner from `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. 6. After Numina changes Lean files, use local `check`, `detect-sorry`, and `review` before accepting the patch. Default to the shared Lean workspace for user tasks. Upstream Numina examples or benchmarks may pin their own `lean-toolchain`; that only describes the example project, not the readiness of `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. @@ -26,6 +26,8 @@ Do not commit runtime state, API keys, generated results, or local machine paths Claude authentication can come from the user's normal Claude CLI login or environment variables such as `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`. Numina's CLI skills may also need `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, or `AXLE_API_KEY`. +If the user asks whether API keys are needed, answer from the Numina mode: official Numina calls need a working Claude CLI/auth path and may need additional keys for search/tool skills. Direct local Lean validation does not need API keys, but it is not the default Lean Agent mode. + The helper readiness report redacts values and only reports whether keys appear configured. ## Boundary diff --git a/skills/AI4Math-Lean-Agents/schemas/result.schema.json b/skills/AI4Math-Lean-Agents/schemas/result.schema.json index 7302666..b3f4dff 100644 --- a/skills/AI4Math-Lean-Agents/schemas/result.schema.json +++ b/skills/AI4Math-Lean-Agents/schemas/result.schema.json @@ -20,6 +20,7 @@ "configuration_status": {"type": "string"}, "missing_config": {"type": "array", "items": {"type": "string"}}, "required_inputs": {"type": "array", "items": {"type": "string"}}, + "numina_workflow": {"type": "array", "items": {"type": "string"}}, "direct_workflow": {"type": "array", "items": {"type": "string"}}, "changed_files": {"type": "array", "items": {"type": "string"}}, "errors": {"type": "array", "items": {"type": "object", "additionalProperties": true}}, diff --git a/skills/AI4Math-Lean-Agents/schemas/task.schema.json b/skills/AI4Math-Lean-Agents/schemas/task.schema.json index c54bb6f..6af95e8 100644 --- a/skills/AI4Math-Lean-Agents/schemas/task.schema.json +++ b/skills/AI4Math-Lean-Agents/schemas/task.schema.json @@ -8,8 +8,8 @@ "type": "string", "enum": ["check", "configure", "prove_theorem", "formalize_statement", "repair_file", "complete_sorries", "batch", "review", "minimize_failure"] }, - "agent_mode": {"type": "string", "enum": ["direct-coding-agent"], "default": "direct-coding-agent"}, - "backend": {"type": "string", "enum": ["none"], "default": "none"}, + "agent_mode": {"type": "string", "enum": ["numina-agent", "direct-validation-fallback"], "default": "numina-agent"}, + "backend": {"type": "string", "enum": ["official-numina", "none"], "default": "official-numina"}, "cwd": {"type": "string"}, "file": {"type": "string"}, "folder": {"type": "string"}, diff --git a/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py b/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py index 092bb28..efd2a9b 100644 --- a/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py +++ b/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py @@ -51,10 +51,10 @@ def add_common(parser: argparse.ArgumentParser) -> None: def build_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description="AI4Math direct Lean coding-agent skill CLI") + parser = argparse.ArgumentParser(description="AI4Math Numina Lean Agent orchestration CLI") sub = parser.add_subparsers(dest="command", required=True) - env = sub.add_parser("env", help="Inspect direct Lean agent environment") + env = sub.add_parser("env", help="Inspect Lean workspace and Numina Agent environment") add_common(env) env.add_argument("--target", default=None) @@ -78,7 +78,7 @@ def build_parser() -> argparse.ArgumentParser: configure_parser.add_argument("--project-name", default=None, help="Lean project name for official Numina tutorial setup") for name in ("prove", "formalize", "repair", "complete-sorries"): - proof = sub.add_parser(name, help=f"Prepare a direct coding-agent {name} task") + proof = sub.add_parser(name, help=f"Prepare a Numina Agent {name} task") add_common(proof) proof.add_argument("--file", required=True) proof.add_argument("--target", default=None) @@ -89,7 +89,7 @@ def build_parser() -> argparse.ArgumentParser: if name == "formalize": proof.add_argument("--statement-file", default=None) - batch = sub.add_parser("batch", help="Prepare a direct coding-agent folder task") + batch = sub.add_parser("batch", help="Prepare a Numina Agent folder task") add_common(batch) batch.add_argument("--folder", required=True) batch.add_argument("--max-rounds", type=int, default=5) diff --git a/skills/AI4Math-Lean-Agents/scripts/configure_lean.py b/skills/AI4Math-Lean-Agents/scripts/configure_lean.py index 16a5dd7..522d22b 100644 --- a/skills/AI4Math-Lean-Agents/scripts/configure_lean.py +++ b/skills/AI4Math-Lean-Agents/scripts/configure_lean.py @@ -72,10 +72,10 @@ def inspect_environment(cwd: str | Path = ".", config_path: str | Path | None = "configuration_status": "configured" if not missing else "missing_config", "cwd": str(cwd_path), "agent": { - "mode": "direct-coding-agent", - "backend": "none", - "numina_required": False, - "numina_runtime": "optional-official-runtime", + "mode": "numina-agent", + "backend": "official-numina", + "numina_required": True, + "numina_runtime": "default-official-runtime", }, "lean": { "target": str(target_path), @@ -175,8 +175,8 @@ def configure( "allow_user_project_version_changes": False, }, "agent": { - "mode": "direct-coding-agent", - "backend": "none", + "mode": "numina-agent", + "backend": "official-numina", }, }) diff --git a/skills/AI4Math-Lean-Agents/scripts/direct_task.py b/skills/AI4Math-Lean-Agents/scripts/direct_task.py index db80b63..edd65f5 100644 --- a/skills/AI4Math-Lean-Agents/scripts/direct_task.py +++ b/skills/AI4Math-Lean-Agents/scripts/direct_task.py @@ -49,8 +49,10 @@ def build_direct_task( missing.append("target") next_actions = [ - "Read the target Lean file and identify the exact declaration or error.", - "Run check or lake env lean after each small edit.", + "Inspect Numina readiness and confirm the target project/file.", + "Explain the official Numina run command, prompt, max rounds, result directory, and credential state before approval.", + "Run the official Numina Lean Agent after approval.", + "Run check or lake env lean on Numina output.", "Keep theorem statements unchanged unless the user explicitly approves a change.", "Stop when the file verifies without sorry/admit/axiom, or return minimize-failure output.", ] @@ -61,9 +63,9 @@ def build_direct_task( return { "ok": not missing, - "status": "direct_task_ready" if not missing else "missing_config", - "agent_mode": "direct-coding-agent", - "backend": "none", + "status": "numina_task_ready" if not missing else "missing_config", + "agent_mode": "numina-agent", + "backend": "official-numina", "task_type": task_type, "target": str(target_path), "cwd": str(cwd_path), @@ -79,8 +81,8 @@ def build_direct_task( "max_rounds": max_rounds, "missing_config": missing, "required_inputs": ["existing Lake project or shared reusable managed workspace"] if "lean_workspace" in missing else [], - "recommended_next_action": "run configure --create-workspace for the shared workspace or move target into a Lake project" if missing else "coding agent should edit/check directly", - "direct_workflow": next_actions, + "recommended_next_action": "run configure --create-workspace for the shared workspace or move target into a Lake project" if missing else "inspect Numina readiness, explain the official run, then call Numina after approval", + "numina_workflow": next_actions, } diff --git a/skills/AI4Math-Lean-Agents/scripts/tool_status.py b/skills/AI4Math-Lean-Agents/scripts/tool_status.py index ad8ba41..bb3383c 100644 --- a/skills/AI4Math-Lean-Agents/scripts/tool_status.py +++ b/skills/AI4Math-Lean-Agents/scripts/tool_status.py @@ -76,4 +76,4 @@ def _recommend( return "install git before using Lake projects with remote dependencies" if missing_lean: return "install Lean/elan before creating the reusable Lean workspace" - return "ready for direct Lean coding-agent workflow" + return "ready for Numina Agent orchestration and local Lean validation" diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py index 041324f..45f1a41 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py @@ -105,30 +105,36 @@ def _guidance_first_check() -> dict[str, Any]: required_phrases = [ "## Agent Playbook", "## Helper Toolbox", + "In this skill, Lean Agent means the official Numina Lean Agent runtime.", + "Default execution mode is Numina Agent mode.", + "The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation.", + "Direct Lean editing is a validation and fallback path, not the default Lean Agent mode.", "Lead the interaction; do not wait for the user to drive every step.", "If the user's language is ambiguous, default to Chinese.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", - "Opening readiness should inspect both direct Lean and optional Numina status before recommending work.", - "Do not say Numina is unnecessary before checking or explaining its readiness.", + "Opening readiness should inspect Numina readiness before recommending work.", + "Do not say API keys are unnecessary until the Numina mode is clear.", "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "offer a small next-step menu", "Ask at most one blocking question at a time.", "The bundled CLI is a helper toolbox, not the workflow driver.", "Use official Numina through a human-in-the-loop runtime workflow.", "Do not turn helper commands into a closed proof workflow.", - "Do not let helper command availability override a better direct coding-agent path.", + "Do not redefine Lean Agent as the coding agent.", ] missing = [phrase for phrase in required_phrases if phrase not in text] orchestration_required = [ "## Session Opening", + "In this skill, Lean Agent means the official Numina Lean Agent runtime.", + "Default execution mode is Numina Agent mode.", "Lead the interaction; do not wait for the user to drive every step.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", - "Opening readiness should inspect both direct Lean and optional Numina status before recommending work.", - "Do not say Numina is unnecessary before checking or explaining its readiness.", + "Opening readiness should inspect Numina readiness before recommending work.", + "Do not say API keys are unnecessary until the Numina mode is clear.", "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "A good opening ends with one decision question, not a checklist.", ] @@ -137,6 +143,8 @@ def _guidance_first_check() -> dict[str, Any]: openai_required = [ "请用中文开始", "如果用户明确使用其他语言", + "Lean Agent 默认指 Numina", + "先检查 Numina readiness", ] openai_missing = [phrase for phrase in openai_required if phrase not in openai_yaml] return { diff --git a/skills/AI4Math-Lean-Agents/tests/test_cli.py b/skills/AI4Math-Lean-Agents/tests/test_cli.py index f18d0a0..bbf9d7f 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_cli.py +++ b/skills/AI4Math-Lean-Agents/tests/test_cli.py @@ -18,7 +18,7 @@ class CliTests(unittest.TestCase): - def test_dry_run_prove_outputs_direct_task(self) -> None: + def test_dry_run_prove_outputs_numina_task(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) workspace = root / ".ai4math" / "lean-workspace" @@ -47,9 +47,9 @@ def test_dry_run_prove_outputs_direct_task(self) -> None: self.assertEqual(result.returncode, 0, result.stderr) payload = json.loads(result.stdout) self.assertEqual(payload["status"], "dry_run") - self.assertEqual(payload["agent_mode"], "direct-coding-agent") - self.assertEqual(payload["backend"], "none") - self.assertIn("direct_workflow", payload) + self.assertEqual(payload["agent_mode"], "numina-agent") + self.assertEqual(payload["backend"], "official-numina") + self.assertIn("numina_workflow", payload) self.assertNotIn("command", payload) def test_check_skip_build_outputs_json(self) -> None: diff --git a/skills/AI4Math-Lean-Agents/tests/test_common_config.py b/skills/AI4Math-Lean-Agents/tests/test_common_config.py index 7637370..b6aff36 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_common_config.py +++ b/skills/AI4Math-Lean-Agents/tests/test_common_config.py @@ -17,14 +17,14 @@ def test_load_toml_has_python39_fallback(self) -> None: with tempfile.TemporaryDirectory() as tmp: path = Path(tmp) / "config.toml" path.write_text( - '[agent]\nmode = "direct-coding-agent"\nbackend = "none"\n' + '[agent]\nmode = "numina-agent"\nbackend = "official-numina"\n' '[lean]\nreuse_managed_workspace = true\n', encoding="utf-8", ) with patch("common.tomllib", None): data = load_toml(path) - self.assertEqual(data["agent"]["backend"], "none") + self.assertEqual(data["agent"]["backend"], "official-numina") self.assertTrue(data["lean"]["reuse_managed_workspace"]) def test_expand_path_preserves_symlink_text(self) -> None: diff --git a/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py b/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py index 26fdf2f..9de11b9 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py +++ b/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py @@ -15,7 +15,7 @@ class ConfigureLeanTests(unittest.TestCase): - def test_existing_lean_project_is_direct_agent_ready(self) -> None: + def test_existing_lean_project_is_numina_agent_ready(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) target = root / "Main.lean" @@ -28,9 +28,9 @@ def test_existing_lean_project_is_direct_agent_ready(self) -> None: result = inspect_environment(root, target=target) self.assertTrue(result["ok"]) - self.assertEqual(result["agent"]["mode"], "direct-coding-agent") - self.assertEqual(result["agent"]["backend"], "none") - self.assertFalse(result["agent"]["numina_required"]) + self.assertEqual(result["agent"]["mode"], "numina-agent") + self.assertEqual(result["agent"]["backend"], "official-numina") + self.assertTrue(result["agent"]["numina_required"]) self.assertEqual(result["missing_config"], []) self.assertIn("numina", result) self.assertIn("readiness", result["numina"]) @@ -46,8 +46,8 @@ def test_save_local_writes_lean_agent_config(self) -> None: self.assertFalse(result["ok"]) self.assertEqual(result["status"], "missing_config") - self.assertEqual(local["agent"]["backend"], "none") - self.assertEqual(local["agent"]["mode"], "direct-coding-agent") + self.assertEqual(local["agent"]["backend"], "official-numina") + self.assertEqual(local["agent"]["mode"], "numina-agent") self.assertEqual(local["lean"]["preferred_toolchain"], "leanprover/lean4:v4.28.0") self.assertIn("lean_agent.local.toml", (root / ".ai4math" / ".gitignore").read_text()) diff --git a/skills/AI4Math-Lean-Agents/tests/test_direct_task.py b/skills/AI4Math-Lean-Agents/tests/test_direct_task.py index dd5d82a..b462db8 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_direct_task.py +++ b/skills/AI4Math-Lean-Agents/tests/test_direct_task.py @@ -14,7 +14,7 @@ class DirectTaskTests(unittest.TestCase): - def test_managed_workspace_routes_standalone_file_without_backend(self) -> None: + def test_managed_workspace_routes_standalone_file_to_numina_agent(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) workspace = root / ".ai4math" / "lean-workspace" @@ -28,9 +28,9 @@ def test_managed_workspace_routes_standalone_file_without_backend(self) -> None: result = build_direct_task("prove", root, target) self.assertTrue(result["ok"]) - self.assertEqual(result["status"], "direct_task_ready") - self.assertEqual(result["agent_mode"], "direct-coding-agent") - self.assertEqual(result["backend"], "none") + self.assertEqual(result["status"], "numina_task_ready") + self.assertEqual(result["agent_mode"], "numina-agent") + self.assertEqual(result["backend"], "official-numina") self.assertEqual(result["workspace_mode"], "managed_workspace") self.assertEqual(result["missing_config"], []) @@ -46,7 +46,7 @@ def test_missing_workspace_reports_required_input(self) -> None: self.assertFalse(result["ok"]) self.assertEqual(result["status"], "missing_config") self.assertIn("lean_workspace", result["missing_config"]) - self.assertEqual(result["backend"], "none") + self.assertEqual(result["backend"], "official-numina") def test_dry_run_marks_ready_task_without_external_command(self) -> None: with tempfile.TemporaryDirectory() as tmp: @@ -60,7 +60,7 @@ def test_dry_run_marks_ready_task_without_external_command(self) -> None: self.assertTrue(result["ok"]) self.assertEqual(result["status"], "dry_run") - self.assertEqual(result["backend"], "none") + self.assertEqual(result["backend"], "official-numina") self.assertNotIn("command", result) From 81f04bb0aa2c61768e7d515d3064db377164016d Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 25 May 2026 12:35:28 +0800 Subject: [PATCH 17/37] Add bundled Lean smoke test --- .cursor/rules/ai4math-lean-agents.mdc | 2 +- .opencode/agents/ai4math-lean-agents.md | 1 + AGENTS.md | 1 + CLAUDE.md | 1 + GEMINI.md | 1 + skills/AI4Math-Lean-Agents/SKILL.md | 3 +- skills/AI4Math-Lean-Agents/agents/openai.yaml | 2 +- .../examples/smoke/NuminaSmoke.lean | 7 ++ .../references/interactive_orchestration.md | 3 +- .../AI4Math-Lean-Agents/scripts/ai4m_lean.py | 10 +++ .../AI4Math-Lean-Agents/scripts/smoke_test.py | 75 +++++++++++++++++++ .../scripts/verify_delivery.py | 14 ++++ skills/AI4Math-Lean-Agents/tests/test_cli.py | 17 +++++ 13 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 skills/AI4Math-Lean-Agents/examples/smoke/NuminaSmoke.lean create mode 100644 skills/AI4Math-Lean-Agents/scripts/smoke_test.py diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/ai4math-lean-agents.mdc index d7f18c6..085ca6d 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/ai4math-lean-agents.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. -In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation; direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation; direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/ai4math-lean-agents.md index 4f3a3d3..fe8acee 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/ai4math-lean-agents.md @@ -17,6 +17,7 @@ Rules: - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +- Use the bundled smoke test when no user target is available. - Opening readiness should inspect Numina readiness before recommending work. - Do not say API keys are unnecessary until the Numina mode is clear. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. diff --git a/AGENTS.md b/AGENTS.md index a6aec21..55ce95e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,6 +12,7 @@ Core rules: - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +- Use the bundled smoke test when no user target is available. - Opening readiness should inspect Numina readiness before recommending work. - Do not say API keys are unnecessary until the Numina mode is clear. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. diff --git a/CLAUDE.md b/CLAUDE.md index 54cb5b6..e06ce11 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,6 +12,7 @@ Match the user's language by default. If the user's language is ambiguous, defau Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +Use the bundled smoke test when no user target is available. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. diff --git a/GEMINI.md b/GEMINI.md index 685bef8..81ae787 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -12,6 +12,7 @@ Match the user's language by default. If the user's language is ambiguous, defau Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. +Use the bundled smoke test when no user target is available. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/AI4Math-Lean-Agents/SKILL.md index 0849d56..ff46aaf 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/AI4Math-Lean-Agents/SKILL.md @@ -13,7 +13,7 @@ Match the user's language by default. If the user's language is ambiguous, defau Lead the interaction; do not wait for the user to drive every step. When the user's request is broad or underspecified, first orient yourself to the Lean project/workspace state, then propose the next useful action in plain language. Do not open with a passive "send me the file" checklist when you can inspect context or offer a concrete starting path. -If no target is available, run or propose a safe local smoke/readiness check. Then recommend a default path, such as checking Numina readiness, preparing the shared workspace as Numina's target project, or running a tiny shared-workspace theorem before an official Numina call. Avoid ending with only "send me a file" or an equivalent passive handoff. +If no target is available, run or propose a safe local smoke/readiness check. Use the bundled smoke test when no user target is available. Then recommend a default path, such as checking Numina readiness, preparing the shared workspace as Numina's target project, or running the built-in smoke theorem before an official Numina call. Avoid ending with only "send me a file" or an equivalent passive handoff. The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, `rg`, Lean/Lake validation, repository context, and the official Numina runner. Use helper commands only when their deterministic output is useful. @@ -46,6 +46,7 @@ Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk - `env` / `doctor`: inspect Lean workspace, local tool availability, and Numina readiness. - `configure --create-workspace`: create or reuse the shared managed workspace. - `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`. +- `smoke-test`: run the bundled `examples/smoke/NuminaSmoke.lean` target in the shared workspace without external API calls. - `check`: run a structured Lean/Lake validation. - `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. - `minimize-failure`: extract a compact failing Lean fragment. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/AI4Math-Lean-Agents/agents/openai.yaml index 91eaecc..ee29cee 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/AI4Math-Lean-Agents/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: AI4Math Lean Agents short_description: Interactive Lean 4 verification through the official Numina Lean Agent runtime with reusable mathlib workspaces. -default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。Lean Agent 默认指 Numina 官方 Lean Agent runtime,不要把 coding agent 重新定义成 Lean Agent。先检查 Numina readiness、共享 workspace、Claude/API 凭据和本地 Lean 验收能力,再推荐下一步。不要在 Numina 模式明确前说 API key 不需要。用户任务默认使用共享 Lean workspace;upstream Numina 示例只是 demo,可能 pin 不同 toolchain。一次最多问一个阻塞问题。coding agent 负责部署、配置、调用 Numina,并用本地 Lean/Lake 验收结果;direct Lean 只是验证或 fallback。 +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。Lean Agent 默认指 Numina 官方 Lean Agent runtime,不要把 coding agent 重新定义成 Lean Agent。先检查 Numina readiness、共享 workspace、Claude/API 凭据和本地 Lean 验收能力,再推荐下一步。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。不要在 Numina 模式明确前说 API key 不需要。用户任务默认使用共享 Lean workspace;upstream Numina 示例只是 demo,可能 pin 不同 toolchain。一次最多问一个阻塞问题。coding agent 负责部署、配置、调用 Numina,并用本地 Lean/Lake 验收结果;direct Lean 只是验证或 fallback。 diff --git a/skills/AI4Math-Lean-Agents/examples/smoke/NuminaSmoke.lean b/skills/AI4Math-Lean-Agents/examples/smoke/NuminaSmoke.lean new file mode 100644 index 0000000..382a189 --- /dev/null +++ b/skills/AI4Math-Lean-Agents/examples/smoke/NuminaSmoke.lean @@ -0,0 +1,7 @@ +import Mathlib + +theorem ai4math_numina_smoke_add_zero (n : Nat) : n + 0 = n := by + simp + +theorem ai4math_numina_smoke_le_succ (n : Nat) : n <= n + 1 := by + omega diff --git a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md index bae068e..f0a2ec1 100644 --- a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md +++ b/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md @@ -24,12 +24,13 @@ When checking Numina, distinguish runtime readiness from upstream demo readiness A language switch is not a task reset. Restate the current state in the user's language, keep the prior diagnosis, and continue with the recommended next action instead of returning to generic intake. -If no target is available, run or propose a safe local smoke/readiness check. Good examples are `lake env lean` against the shared workspace, `lake build` for the user's current Lake project when it is already present, or a helper `doctor` check when environment status is the question. Avoid ending with only "send me a file" or an equivalent passive handoff. +If no target is available, run or propose a safe local smoke/readiness check. Use the bundled smoke test when no user target is available. Good examples are `smoke-test` against `examples/smoke/NuminaSmoke.lean`, `lake build` for the user's current Lake project when it is already present, or a helper `doctor` check when environment status is the question. Avoid ending with only "send me a file" or an equivalent passive handoff. If no precise target is provided, offer a small menu and recommend one path. For example: - configure missing Numina credentials/auth; - run a Numina readiness check; +- run the bundled smoke test to verify the local Lean/mathlib validation layer; - prepare the shared workspace as the Numina target project; - call Numina on a natural-language/LaTeX theorem or Lean file; - inspect a Lean/Lake project and summarize whether Numina can target it. diff --git a/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py b/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py index efd2a9b..67b91aa 100644 --- a/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py +++ b/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py @@ -12,6 +12,7 @@ from direct_task import run_direct_task from extract_minimal_failure import extract from numina_runtime import numina_readiness +from smoke_test import run_smoke_test from tool_status import doctor from validate_patch import review_files from verify_delivery import verify as verify_delivery @@ -67,6 +68,11 @@ def build_parser() -> argparse.ArgumentParser: check.add_argument("--skip-build", action="store_true") check.add_argument("--timeout", type=int, default=300) + smoke = sub.add_parser("smoke-test", help="Run the bundled Lean smoke target in the shared workspace") + add_common(smoke) + smoke.add_argument("--timeout", type=int, default=120) + smoke.add_argument("--dry-run", action="store_true") + configure_parser = sub.add_parser("configure", help="Inspect or create local Lean workspace configuration") add_common(configure_parser) configure_parser.add_argument("--target", default=None) @@ -142,6 +148,10 @@ def main(argv: list[str] | None = None) -> None: result = check_project(args.cwd, skip_build=args.skip_build, timeout=args.timeout) _finish(result, args.json_output, fail_code=EXIT_LEAN_FAILED) + if args.command == "smoke-test": + result = run_smoke_test(args.cwd, config_path=args.config, timeout=args.timeout, dry_run=args.dry_run) + _finish(result, args.json_output, fail_code=EXIT_LEAN_FAILED) + if args.command == "configure": result = configure( args.cwd, diff --git a/skills/AI4Math-Lean-Agents/scripts/smoke_test.py b/skills/AI4Math-Lean-Agents/scripts/smoke_test.py new file mode 100644 index 0000000..83fcef3 --- /dev/null +++ b/skills/AI4Math-Lean-Agents/scripts/smoke_test.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any + +from common import run_command +from configure_lean import inspect_environment +from tool_status import find_tool + + +SKILL_ROOT = Path(__file__).resolve().parents[1] +SMOKE_FILE = SKILL_ROOT / "examples" / "smoke" / "NuminaSmoke.lean" + + +def run_smoke_test( + cwd: str | Path = ".", + *, + config_path: str | Path | None = None, + timeout: int = 120, + dry_run: bool = False, +) -> dict[str, Any]: + cwd_path = Path(cwd).resolve() + env = inspect_environment(cwd_path, config_path=config_path) + lean = env.get("lean", {}) + workspace_root = lean.get("workspace_project_root") or lean.get("project_root") + lake = find_tool("lake") or "lake" + command = [lake, "env", "lean", str(SMOKE_FILE)] + if dry_run: + return { + "ok": SMOKE_FILE.exists(), + "status": "dry_run", + "cwd": str(cwd_path), + "project_root": str(workspace_root) if workspace_root else None, + "smoke_file": str(SMOKE_FILE), + "command": command, + "missing_config": [] if workspace_root else ["lean_workspace"], + "theorems": [ + "ai4math_numina_smoke_add_zero", + "ai4math_numina_smoke_le_succ", + ], + "external_api_call": False, + "recommended_next_action": "run the bundled smoke target in the shared workspace before an official Numina call", + } + if not workspace_root: + return { + "ok": False, + "status": "missing_lean_workspace", + "cwd": str(cwd_path), + "smoke_file": str(SMOKE_FILE), + "project_root": None, + "environment": env, + "recommended_next_action": "run configure --create-workspace, then rerun smoke-test", + } + + result: dict[str, Any] = { + "ok": True, + "status": "ready", + "cwd": str(cwd_path), + "project_root": str(workspace_root), + "smoke_file": str(SMOKE_FILE), + "command": command, + "theorems": [ + "ai4math_numina_smoke_add_zero", + "ai4math_numina_smoke_le_succ", + ], + "external_api_call": False, + "recommended_next_action": "use this built-in smoke target before a Numina run, then call official Numina after approval", + } + lean_result = run_command(command, cwd=workspace_root, timeout=timeout) + result["lean"] = lean_result + result["ok"] = bool(lean_result.get("ok")) + result["status"] = "ok" if result["ok"] else "lean_smoke_failed" + if not result["ok"]: + result["recommended_next_action"] = "inspect the Lean smoke error, then repair the shared workspace before calling Numina" + return result diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py index 45f1a41..71ae1e0 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py @@ -12,6 +12,7 @@ from configure_lean import inspect_environment from direct_task import run_direct_task from extract_minimal_failure import extract +from smoke_test import run_smoke_test from tool_status import doctor, find_tool from validate_patch import review_files @@ -22,6 +23,7 @@ "agents/openai.yaml", "config/lean_agent.example.toml", "config/numina_runtime.example.toml", + "examples/smoke/NuminaSmoke.lean", "schemas/task.schema.json", "schemas/result.schema.json", "schemas/config.schema.json", @@ -36,6 +38,7 @@ "scripts/configure_lean.py", "scripts/direct_task.py", "scripts/numina_runtime.py", + "scripts/smoke_test.py", "scripts/validate_patch.py", "scripts/extract_minimal_failure.py", ] @@ -52,6 +55,7 @@ "review", "detect-sorry", "minimize-failure", + "smoke-test", "verify-delivery", } @@ -109,6 +113,7 @@ def _guidance_first_check() -> dict[str, Any]: "Default execution mode is Numina Agent mode.", "The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation.", "Direct Lean editing is a validation and fallback path, not the default Lean Agent mode.", + "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", "If the user's language is ambiguous, default to Chinese.", "A language switch is not a task reset.", @@ -129,6 +134,7 @@ def _guidance_first_check() -> dict[str, Any]: "## Session Opening", "In this skill, Lean Agent means the official Numina Lean Agent runtime.", "Default execution mode is Numina Agent mode.", + "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", @@ -184,6 +190,7 @@ def verify( dry_run = run_direct_task("prove", dry_root, dry_target, dry_run=True) review = review_files(fixtures / "before.lean", fixtures / "after_bad.lean") failure = extract(fixtures / "failure.lean", target=None, run_lean=False) + smoke = run_smoke_test(cwd_path, dry_run=True) tool_report = doctor(cwd_path) if require_environment else None env_report = inspect_environment(cwd_path) if require_environment else None @@ -214,6 +221,7 @@ def verify( "dry_run_prove": bool(dry_run.get("ok") and dry_run.get("status") == "dry_run"), "patch_guard": bool(not review.get("ok") and review.get("findings")), "minimal_failure": bool(failure.get("ok") and failure.get("minimal_failure", {}).get("snippet")), + "bundled_smoke_test": bool(smoke.get("ok") and smoke.get("status") == "dry_run" and Path(smoke.get("smoke_file", "")).exists()), "package_hygiene": bool(hygiene.get("ok")), } if require_environment: @@ -258,6 +266,12 @@ def verify( "start_line": failure.get("minimal_failure", {}).get("start_line"), "end_line": failure.get("minimal_failure", {}).get("end_line"), }, + "bundled_smoke_test": { + "ok": smoke.get("ok"), + "status": smoke.get("status"), + "smoke_file": smoke.get("smoke_file"), + "project_root": smoke.get("project_root"), + }, "hygiene": hygiene, "tool_environment": tool_report, "lean_agent_environment": env_report, diff --git a/skills/AI4Math-Lean-Agents/tests/test_cli.py b/skills/AI4Math-Lean-Agents/tests/test_cli.py index bbf9d7f..0da0223 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_cli.py +++ b/skills/AI4Math-Lean-Agents/tests/test_cli.py @@ -68,6 +68,23 @@ def test_check_skip_build_outputs_json(self) -> None: self.assertTrue(payload["ok"]) self.assertEqual(payload["toolchain"], "leanprover/lean4:v4.26.0") + def test_smoke_test_dry_run_uses_bundled_target(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + result = subprocess.run( + [sys.executable, str(CLI), "smoke-test", "--cwd", str(root), "--dry-run"], + text=True, + capture_output=True, + check=False, + env={**os.environ, "AI4MATH_HOME": str(root / "shared-ai4math"), "AI4MATH_LEAN_WORKSPACE": ""}, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertTrue(payload["ok"]) + self.assertEqual(payload["status"], "dry_run") + self.assertTrue(payload["smoke_file"].endswith("examples/smoke/NuminaSmoke.lean")) + self.assertFalse(payload["external_api_call"]) + def test_doctor_outputs_tool_report(self) -> None: result = subprocess.run( [sys.executable, str(CLI), "doctor", "--cwd", str(SKILL_ROOT)], From 63f52ff2f477c410e1b7dca25537826e6c98996a Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Mon, 15 Jun 2026 20:33:01 +0800 Subject: [PATCH 18/37] docs: normalize AI4Math skill adapter --- .codex/INSTALL.md | 14 ++++ .opencode/INSTALL.md | 11 +++ AGENTS.md | 2 +- CLAUDE.md | 2 +- GEMINI.md | 2 +- README.md | 48 +++++++++++++ README.zh-CN.md | 68 +++++++++++++++++++ SKILL.md | 23 +++++++ .../tests/test_numina_runtime.py | 6 +- 9 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 .codex/INSTALL.md create mode 100644 .opencode/INSTALL.md create mode 100644 README.zh-CN.md create mode 100644 SKILL.md diff --git a/.codex/INSTALL.md b/.codex/INSTALL.md new file mode 100644 index 0000000..c54594f --- /dev/null +++ b/.codex/INSTALL.md @@ -0,0 +1,14 @@ +# Codex Loading Notes + +This repository exposes a shared Skill layer at: + +```text +skills/AI4Math-Lean-Agents/SKILL.md +``` + +Use from the checkout by asking Codex to read `AGENTS.md`, `SKILL.md`, and the +concrete Skill file. For local discovery, sync or link +`skills/AI4Math-Lean-Agents/` into the Codex Skill path used by your +installation, then restart or reload if required. + +Do not duplicate workflow logic in `.codex/`; update the shared Skill layer. diff --git a/.opencode/INSTALL.md b/.opencode/INSTALL.md new file mode 100644 index 0000000..cad95af --- /dev/null +++ b/.opencode/INSTALL.md @@ -0,0 +1,11 @@ +# OpenCode Loading Notes + +This repository exposes a shared Skill layer at: + +```text +skills/AI4Math-Lean-Agents/SKILL.md +``` + +OpenCode can use the repository checkout directly by reading `AGENTS.md`, +`SKILL.md`, and the concrete Skill file. Keep any OpenCode wrapper thin and +point it back to the shared Skill layer. diff --git a/AGENTS.md b/AGENTS.md index 55ce95e..9a66cb8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Agent Instructions -Use the canonical skill at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. +Use the canonical shared Skill layer at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. Core rules: diff --git a/CLAUDE.md b/CLAUDE.md index e06ce11..eb32810 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # Claude Code Instructions -For Lean work in this repository, read and follow: +For Lean work in this repository, read and follow the shared Skill layer: ```text skills/AI4Math-Lean-Agents/SKILL.md diff --git a/GEMINI.md b/GEMINI.md index 81ae787..921ca5b 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -1,6 +1,6 @@ # Gemini Instructions -For Lean 4 formal verification tasks, use the skill instructions at: +For Lean 4 formal verification tasks, use the shared Skill layer at: ```text skills/AI4Math-Lean-Agents/SKILL.md diff --git a/README.md b/README.md index 5fd8930..236ae71 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,40 @@ The canonical skill package lives at: skills/AI4Math-Lean-Agents/ ``` +## Installation / Loading + +Use the repository checkout first. Ask your coding agent to read: + +```text +AGENTS.md +SKILL.md +skills/AI4Math-Lean-Agents/SKILL.md +``` + +If your agent supports local Skill discovery, install or link +`skills/AI4Math-Lean-Agents/` into that agent's Skill path and reload the agent +if needed. Platform notes live in `CLAUDE.md`, `GEMINI.md`, +`.codex/INSTALL.md`, and `.opencode/INSTALL.md`. + +## Quick Start + +```text +Use this repository's Lean workflow. + +Read: +- AGENTS.md +- SKILL.md +- skills/AI4Math-Lean-Agents/SKILL.md + +Goal: + + +Constraints: +- inspect the Lean project first; +- preserve theorem statements unless approved; +- ask before Numina setup, source edits, or final proof claims. +``` + ## What It Supports - Lean project/workspace inspection. @@ -67,6 +101,20 @@ rsync -a --delete skills/AI4Math-Lean-Agents/ ~/.codex/skills/ai4math-lean-agent Then ask the coding agent for Lean formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, or minimal failure extraction. +## How To Interact + +Use a checkpoint loop: + +```text +Lean task -> project inspection -> plan -> approve / revise / reject / skip + -> approved edit or validation -> evidence summary -> next checkpoint +``` + +Use `approve` to run a proposed step, `revise` to update the plan, `reject` to +stop the path, and `skip` to move past a phase. The agent should ask before +theorem statement changes, optional Numina setup, source edits, or final proof +claims. + ## Helper Commands Run commands from the repository root: diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..d695bd3 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,68 @@ +# AI4Math Lean Agents + +[English](README.md) | 简体中文 + +AI4Math Lean Agents 是一个面向 Lean 4 形式化验证的 guidance-first Skill +package。coding agent 直接读取、编辑和检查 Lean 代码;附带 CLI 只是用于环境检查、 +Lean validation、可选 Numina runtime 设置、patch review 和最小失败交接的确定性辅助工具。 + +## 安装 / 加载 + +优先从当前仓库 checkout 使用。让 coding agent 读取: + +```text +AGENTS.md +SKILL.md +skills/AI4Math-Lean-Agents/SKILL.md +``` + +如果目标 agent 支持本地 Skill discovery,可以把 `skills/AI4Math-Lean-Agents/` +安装或软链接到它的 Skill 路径,然后按需 reload 或 restart。Codex、Claude、 +Gemini 和 OpenCode 的薄 adapter 分别见 `.codex/INSTALL.md`、`CLAUDE.md`、 +`GEMINI.md` 和 `.opencode/INSTALL.md`。 + +## 快速开始 + +```text +Use this repository's Lean workflow. + +Read: +- AGENTS.md +- SKILL.md +- skills/AI4Math-Lean-Agents/SKILL.md + +Goal: +<描述 Lean formalization、proof repair、theorem transcription 或 validation 任务> + +Constraints: +- inspect the Lean project first; +- preserve theorem statements unless approved; +- ask before Numina setup, source edits, or final proof claims. +``` + +## 如何交互使用 + +推荐使用 checkpoint 循环: + +```text +Lean 任务 -> 项目检查 -> 计划 -> approve / revise / reject / skip + -> 获批编辑或验证 -> 证据总结 -> 下一轮 checkpoint +``` + +`approve` 表示执行下一步,`revise` 表示先修改计划,`reject` 表示停止当前路线, +`skip` 表示跳过当前阶段。修改 theorem statement、设置 Numina、编辑源码和接受最终 proof +claim 前都应先问用户。 + +## 支持范围 + +- Lean project/workspace inspection。 +- theorem formalization、proof repair、proof completion 和 `sorry` completion。 +- patch review:检查 `sorry`、`admit`、新引入的 `axiom` 和 theorem statement drift。 +- 可选 official `project-numina/numina-lean-agent` runtime 设置和调用。 +- proof blocked 时抽取最小失败 Lean fragment。 + +## 维护者检查 + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +``` diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..3a817a2 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,23 @@ +--- +name: ai4math-lean-agents +description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, Numina runtime setup, or local Lean validation. +--- + +# AI4Math Lean Agents + +This root `SKILL.md` is a compatibility entrypoint for platforms that expect one +top-level Skill file. The shared Skill layer lives at: + +```text +skills/AI4Math-Lean-Agents/SKILL.md +``` + +Read that concrete Skill before Lean work. Keep platform adapters thin and +improve the shared Skill layer first. + +## Operating Boundary + +- Preserve theorem statements unless the user approves a change. +- Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. +- Explain and approve optional Numina runtime setup before executing it. +- Validate final Lean patches locally when possible. diff --git a/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py b/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py index fd834c4..6646a03 100644 --- a/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py +++ b/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py @@ -65,7 +65,7 @@ def test_env_local_is_read_from_numina_runtime_root(self) -> None: env_path.parent.mkdir(parents=True) env_path.write_text( "export ANTHROPIC_AUTH_TOKEN=secret-token\n" - "OPENAI_API_KEY=sk-test\n", + "OPENAI_API_KEY=placeholder-openai-token\n", encoding="utf-8", ) @@ -73,12 +73,12 @@ def test_env_local_is_read_from_numina_runtime_root(self) -> None: values = read_numina_env_local(root) self.assertEqual(values["ANTHROPIC_AUTH_TOKEN"], "secret-token") - self.assertEqual(values["OPENAI_API_KEY"], "sk-test") + self.assertEqual(values["OPENAI_API_KEY"], "placeholder-openai-token") def test_credential_report_redacts_values(self) -> None: report = credential_report({ "ANTHROPIC_AUTH_TOKEN": "secret-token", - "OPENAI_API_KEY": "sk-test", + "OPENAI_API_KEY": "placeholder-openai-token", }) self.assertTrue(report["claude"]["configured"]) From ce8e6eff160cca002f7bd6d47d8f7319d065af29 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Wed, 17 Jun 2026 00:50:21 +0800 Subject: [PATCH 19/37] docs: streamline skill readme usage flow --- README.md | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 236ae71..befed4c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,13 @@ If your agent supports local Skill discovery, install or link if needed. Platform notes live in `CLAUDE.md`, `GEMINI.md`, `.codex/INSTALL.md`, and `.opencode/INSTALL.md`. +Codex-style local install example: + +```bash +mkdir -p ~/.codex/skills +rsync -a --delete skills/AI4Math-Lean-Agents/ ~/.codex/skills/ai4math-lean-agents/ +``` + ## Quick Start ```text @@ -77,30 +84,6 @@ Numina is optional. The public CLI does not expose a parallel `numina-*` workflo └── tests/ ``` -## Use With Coding Agents - -Point your coding agent at the canonical workflow: - -```text -skills/AI4Math-Lean-Agents/SKILL.md -``` - -The repository also includes lightweight adapters for several agent environments: - -- `AGENTS.md` for general repository-aware coding agents. -- `.cursor/rules/ai4math-lean-agents.mdc` for Cursor. -- `.opencode/agents/ai4math-lean-agents.md` for OpenCode. -- `CLAUDE.md` and `GEMINI.md` for agent-specific repository instructions. - -For Codex-style skill installation, sync the skill folder into the user skill directory. The repository does not include a repo-local Codex shim, so a workspace that also has the system skill installed will not show two `ai4math-lean-agents` entries. - -```bash -mkdir -p ~/.codex/skills -rsync -a --delete skills/AI4Math-Lean-Agents/ ~/.codex/skills/ai4math-lean-agents/ -``` - -Then ask the coding agent for Lean formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, or minimal failure extraction. - ## How To Interact Use a checkpoint loop: From 99e5236325f97913573bf79afe60d885b1e02f5f Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Thu, 18 Jun 2026 17:31:41 +0800 Subject: [PATCH 20/37] Clarify Lean agent handoff role --- README.md | 22 +++++++++++++++++++++- README.zh-CN.md | 20 ++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index befed4c..eb8d18b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # AI4Math Lean Agents -AI4Math Lean Agents is a guidance-first skill package for Lean 4 formal verification with coding agents. The active coding agent directly reads, edits, and checks Lean code; the bundled CLI is only a deterministic helper toolbox for environment checks, Lean validation, optional official Numina runtime setup, patch review, and minimal failure handoff. +AI4Math Lean Agents is a guidance-first skill package for Lean 4 formal +verification with coding agents. The default Lean Agent path orchestrates the +official Numina Lean Agent runtime; local Lean editing is the validation and +fallback path when Numina is unavailable, declined, or insufficient. The bundled +CLI is only a deterministic helper toolbox for environment checks, Lean +validation, Numina readiness/setup, patch review, and minimal failure handoff. The canonical skill package lives at: @@ -8,6 +13,21 @@ The canonical skill package lives at: skills/AI4Math-Lean-Agents/ ``` +## AI4Math Role + +This skill is the Lean 4 formalization and proof-repair layer in the AI4Math +stack. Use it when a theorem statement, proof obligation, or generated proof +candidate needs machine-checked Lean evidence rather than informal proof review. + +## Handoff + +Upstream inputs may come from `agentic-rethlas-proving`, +`discover-math-problems`, `paper-to-skill`, or a user Lean project. Handoff +artifacts should include the intended theorem statement, allowed assumptions, +imports, current Lean errors or goals, and any proof blueprint. Return validated +Lean patches, minimized failures, or blocked proof obligations without changing +the theorem statement unless the user approves. + ## Installation / Loading Use the repository checkout first. Ask your coding agent to read: diff --git a/README.zh-CN.md b/README.zh-CN.md index d695bd3..4af5c48 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,9 +2,25 @@ [English](README.md) | 简体中文 +本中文 README 聚焦安装、交互和 AI4Math 角色;完整 helper 和 validation 细节见英文 README。 + AI4Math Lean Agents 是一个面向 Lean 4 形式化验证的 guidance-first Skill -package。coding agent 直接读取、编辑和检查 Lean 代码;附带 CLI 只是用于环境检查、 -Lean validation、可选 Numina runtime 设置、patch review 和最小失败交接的确定性辅助工具。 +package。默认 Lean Agent 路径是编排官方 Numina Lean Agent runtime;当 Numina 不可用、 +用户拒绝或结果不足时,本地 Lean 编辑才是 validation 和 fallback 路径。附带 CLI 只是用于 +环境检查、Lean validation、Numina readiness/setup、patch review 和最小失败交接的确定性辅助工具。 + +## AI4Math 角色 + +这个 Skill 是 AI4Math 体系里的 Lean 4 形式化和 proof repair 层。当 theorem statement、 +proof obligation 或生成的 proof candidate 需要机器检查的 Lean 证据,而不是只做非形式化 +proof review 时,使用它。 + +## 交接 + +上游可能来自 `agentic-rethlas-proving`、`discover-math-problems`、`paper-to-skill`, +或用户自己的 Lean project。交接时应包含 intended theorem statement、allowed assumptions、 +imports、当前 Lean errors/goals 和 proof blueprint。完成后返回 validated Lean patch、 +minimized failure 或 blocked proof obligations;除非用户批准,不改变 theorem statement。 ## 安装 / 加载 From d584e858b3eb887b3433b38f7c8e0512dcc8dd21 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Thu, 18 Jun 2026 18:00:49 +0800 Subject: [PATCH 21/37] Add Chinese README link --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index eb8d18b..b1ffee6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # AI4Math Lean Agents +Chinese guide: [README.zh-CN.md](README.zh-CN.md) + AI4Math Lean Agents is a guidance-first skill package for Lean 4 formal verification with coding agents. The default Lean Agent path orchestrates the official Numina Lean Agent runtime; local Lean editing is the validation and From 66e9f91f803954fe05aaa519567c2bc98523696e Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 19 Jun 2026 10:47:08 +0800 Subject: [PATCH 22/37] Normalize AI4Math skill naming --- .codex/INSTALL.md | 4 +-- ...lean-agents.mdc => lean-formalization.mdc} | 6 ++-- .github/workflows/verify.yml | 6 ++-- .opencode/INSTALL.md | 2 +- ...h-lean-agents.md => lean-formalization.md} | 4 +-- AGENTS.md | 4 +-- CLAUDE.md | 2 +- GEMINI.md | 4 +-- README.md | 36 +++++++++---------- README.zh-CN.md | 14 ++++---- SKILL.md | 6 ++-- .../SKILL.md | 4 +-- .../agents/openai.yaml | 2 +- .../config/env.example | 0 .../config/lean_agent.example.toml | 0 .../config/numina_runtime.example.toml | 0 .../examples/smoke/NuminaSmoke.lean | 0 .../prompts/complete_sorries.md | 0 .../prompts/formalize_statement.md | 0 .../prompts/prove_theorem.md | 0 .../prompts/repair_lean_file.md | 0 .../references/direct_lean_workflow.md | 0 .../references/failure_taxonomy.md | 0 .../references/interactive_orchestration.md | 0 .../references/lean_runtime_configuration.md | 0 .../references/numina_reverse_analysis.md | 0 .../references/numina_runtime.md | 0 .../references/review_checklist.md | 0 .../schemas/config.schema.json | 0 .../schemas/result.schema.json | 0 .../schemas/task.schema.json | 0 .../scripts/ai4m_lean.py | 0 .../scripts/check_lean_project.py | 0 .../scripts/common.py | 0 .../scripts/configure_lean.py | 0 .../scripts/detect_sorry.py | 0 .../scripts/direct_task.py | 0 .../scripts/extract_minimal_failure.py | 0 .../scripts/numina_runtime.py | 0 .../scripts/smoke_test.py | 0 .../scripts/tool_status.py | 0 .../scripts/validate_patch.py | 0 .../scripts/verify_delivery.py | 2 +- .../tests/fixtures/after_bad.lean | 0 .../fixtures/after_statement_changed.lean | 0 .../tests/fixtures/before.lean | 0 .../tests/fixtures/failure.lean | 0 .../tests/test_check_lean_project.py | 0 .../tests/test_cli.py | 0 .../tests/test_common_config.py | 0 .../tests/test_configure_lean.py | 0 .../tests/test_detect_sorry.py | 0 .../tests/test_direct_task.py | 0 .../tests/test_numina_runtime.py | 0 .../tests/test_validate_patch.py | 0 55 files changed, 48 insertions(+), 48 deletions(-) rename .cursor/rules/{ai4math-lean-agents.mdc => lean-formalization.mdc} (76%) rename .opencode/agents/{ai4math-lean-agents.md => lean-formalization.md} (96%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/SKILL.md (99%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/agents/openai.yaml (96%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/config/env.example (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/config/lean_agent.example.toml (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/config/numina_runtime.example.toml (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/examples/smoke/NuminaSmoke.lean (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/prompts/complete_sorries.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/prompts/formalize_statement.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/prompts/prove_theorem.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/prompts/repair_lean_file.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/references/direct_lean_workflow.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/references/failure_taxonomy.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/references/interactive_orchestration.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/references/lean_runtime_configuration.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/references/numina_reverse_analysis.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/references/numina_runtime.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/references/review_checklist.md (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/schemas/config.schema.json (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/schemas/result.schema.json (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/schemas/task.schema.json (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/ai4m_lean.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/check_lean_project.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/common.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/configure_lean.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/detect_sorry.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/direct_task.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/extract_minimal_failure.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/numina_runtime.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/smoke_test.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/tool_status.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/validate_patch.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/scripts/verify_delivery.py (99%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/fixtures/after_bad.lean (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/fixtures/after_statement_changed.lean (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/fixtures/before.lean (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/fixtures/failure.lean (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_check_lean_project.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_cli.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_common_config.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_configure_lean.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_detect_sorry.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_direct_task.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_numina_runtime.py (100%) rename skills/{AI4Math-Lean-Agents => lean-formalization}/tests/test_validate_patch.py (100%) diff --git a/.codex/INSTALL.md b/.codex/INSTALL.md index c54594f..ee5ec3f 100644 --- a/.codex/INSTALL.md +++ b/.codex/INSTALL.md @@ -3,12 +3,12 @@ This repository exposes a shared Skill layer at: ```text -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` Use from the checkout by asking Codex to read `AGENTS.md`, `SKILL.md`, and the concrete Skill file. For local discovery, sync or link -`skills/AI4Math-Lean-Agents/` into the Codex Skill path used by your +`skills/lean-formalization/` into the Codex Skill path used by your installation, then restart or reload if required. Do not duplicate workflow logic in `.codex/`; update the shared Skill layer. diff --git a/.cursor/rules/ai4math-lean-agents.mdc b/.cursor/rules/lean-formalization.mdc similarity index 76% rename from .cursor/rules/ai4math-lean-agents.mdc rename to .cursor/rules/lean-formalization.mdc index 085ca6d..cb681c2 100644 --- a/.cursor/rules/ai4math-lean-agents.mdc +++ b/.cursor/rules/lean-formalization.mdc @@ -1,5 +1,5 @@ --- -description: AI4Math Lean Agents workflow for Lean 4 formalization and proof repair +description: Lean Formalization workflow for Lean 4 formalization and proof repair globs: - "**/*.lean" - "**/lakefile.*" @@ -7,8 +7,8 @@ globs: alwaysApply: false --- -Use `skills/AI4Math-Lean-Agents/SKILL.md` as the canonical workflow. +Use `skills/lean-formalization/SKILL.md` as the canonical workflow. -In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation; direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional and should be used only for environment checks, structured validation, Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation; direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/lean-formalization/scripts/` is optional and should be used only for environment checks, structured validation, Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 3a21578..54f6b80 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,4 +1,4 @@ -name: Verify AI4Math Lean Agents +name: Verify Lean Formalization on: push: @@ -16,8 +16,8 @@ jobs: - name: Run unit tests run: | - PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/AI4Math-Lean-Agents/tests + PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/lean-formalization/tests - name: Verify package shape run: | - PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests + PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests diff --git a/.opencode/INSTALL.md b/.opencode/INSTALL.md index cad95af..a3010b2 100644 --- a/.opencode/INSTALL.md +++ b/.opencode/INSTALL.md @@ -3,7 +3,7 @@ This repository exposes a shared Skill layer at: ```text -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` OpenCode can use the repository checkout directly by reading `AGENTS.md`, diff --git a/.opencode/agents/ai4math-lean-agents.md b/.opencode/agents/lean-formalization.md similarity index 96% rename from .opencode/agents/ai4math-lean-agents.md rename to .opencode/agents/lean-formalization.md index fe8acee..f18e48e 100644 --- a/.opencode/agents/ai4math-lean-agents.md +++ b/.opencode/agents/lean-formalization.md @@ -1,11 +1,11 @@ -# AI4Math Lean Agents +# Lean Formalization Use this agent for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. Canonical workflow: ```text -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` Rules: diff --git a/AGENTS.md b/AGENTS.md index 9a66cb8..7e9284b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Agent Instructions -Use the canonical shared Skill layer at `skills/AI4Math-Lean-Agents/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. +Use the canonical shared Skill layer at `skills/lean-formalization/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. Core rules: @@ -24,5 +24,5 @@ Core rules: Useful validation: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` diff --git a/CLAUDE.md b/CLAUDE.md index eb32810..6aac3bc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3,7 +3,7 @@ For Lean work in this repository, read and follow the shared Skill layer: ```text -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` Use Claude Code as the Numina orchestrator and local Lean validator. In this skill, Lean Agent means the official Numina Lean Agent runtime. Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. diff --git a/GEMINI.md b/GEMINI.md index 921ca5b..297f5e8 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -3,7 +3,7 @@ For Lean 4 formal verification tasks, use the shared Skill layer at: ```text -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation. Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. @@ -17,4 +17,4 @@ Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -The helper CLI under `skills/AI4Math-Lean-Agents/scripts/` is optional tooling. It can report and configure the official Numina runtime, but the agent should still validate final Lean patches locally. +The helper CLI under `skills/lean-formalization/scripts/` is optional tooling. It can report and configure the official Numina runtime, but the agent should still validate final Lean patches locally. diff --git a/README.md b/README.md index b1ffee6..81d387c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# AI4Math Lean Agents +# Lean Formalization Chinese guide: [README.zh-CN.md](README.zh-CN.md) -AI4Math Lean Agents is a guidance-first skill package for Lean 4 formal +Lean Formalization is a guidance-first skill package for Lean 4 formal verification with coding agents. The default Lean Agent path orchestrates the official Numina Lean Agent runtime; local Lean editing is the validation and fallback path when Numina is unavailable, declined, or insufficient. The bundled @@ -12,7 +12,7 @@ validation, Numina readiness/setup, patch review, and minimal failure handoff. The canonical skill package lives at: ```text -skills/AI4Math-Lean-Agents/ +skills/lean-formalization/ ``` ## AI4Math Role @@ -23,7 +23,7 @@ candidate needs machine-checked Lean evidence rather than informal proof review. ## Handoff -Upstream inputs may come from `agentic-rethlas-proving`, +Upstream inputs may come from `rethlas-proving`, `discover-math-problems`, `paper-to-skill`, or a user Lean project. Handoff artifacts should include the intended theorem statement, allowed assumptions, imports, current Lean errors or goals, and any proof blueprint. Return validated @@ -37,11 +37,11 @@ Use the repository checkout first. Ask your coding agent to read: ```text AGENTS.md SKILL.md -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` If your agent supports local Skill discovery, install or link -`skills/AI4Math-Lean-Agents/` into that agent's Skill path and reload the agent +`skills/lean-formalization/` into that agent's Skill path and reload the agent if needed. Platform notes live in `CLAUDE.md`, `GEMINI.md`, `.codex/INSTALL.md`, and `.opencode/INSTALL.md`. @@ -49,7 +49,7 @@ Codex-style local install example: ```bash mkdir -p ~/.codex/skills -rsync -a --delete skills/AI4Math-Lean-Agents/ ~/.codex/skills/ai4math-lean-agents/ +rsync -a --delete skills/lean-formalization/ ~/.codex/skills/lean-formalization/ ``` ## Quick Start @@ -60,7 +60,7 @@ Use this repository's Lean workflow. Read: - AGENTS.md - SKILL.md -- skills/AI4Math-Lean-Agents/SKILL.md +- skills/lean-formalization/SKILL.md Goal: @@ -95,7 +95,7 @@ Numina is optional. The public CLI does not expose a parallel `numina-*` workflo ├── .cursor/ # optional Cursor rule ├── .opencode/ # optional OpenCode agent └── skills/ - └── AI4Math-Lean-Agents/ + └── lean-formalization/ ├── SKILL.md ├── agents/ ├── config/ @@ -125,26 +125,26 @@ claims. Run commands from the repository root: ```bash -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py env --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py doctor --cwd . -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --create-workspace -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py check --cwd . --skip-build -python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +python skills/lean-formalization/scripts/ai4m_lean.py env --cwd . +python skills/lean-formalization/scripts/ai4m_lean.py doctor --cwd . +python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace +python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run +python skills/lean-formalization/scripts/ai4m_lean.py check --cwd . --skip-build +python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` The helper CLI is not the proof engine. The coding agent remains responsible for reading Lean errors, editing proofs, choosing proof strategy, and matching the user's language. -For the optional Numina path, read `skills/AI4Math-Lean-Agents/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. +For the optional Numina path, read `skills/lean-formalization/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. ## Validate ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` For a full local Lean workspace check: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index 4af5c48..1ab22d3 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,10 +1,10 @@ -# AI4Math Lean Agents +# Lean Formalization [English](README.md) | 简体中文 本中文 README 聚焦安装、交互和 AI4Math 角色;完整 helper 和 validation 细节见英文 README。 -AI4Math Lean Agents 是一个面向 Lean 4 形式化验证的 guidance-first Skill +Lean Formalization 是一个面向 Lean 4 形式化验证的 guidance-first Skill package。默认 Lean Agent 路径是编排官方 Numina Lean Agent runtime;当 Numina 不可用、 用户拒绝或结果不足时,本地 Lean 编辑才是 validation 和 fallback 路径。附带 CLI 只是用于 环境检查、Lean validation、Numina readiness/setup、patch review 和最小失败交接的确定性辅助工具。 @@ -17,7 +17,7 @@ proof review 时,使用它。 ## 交接 -上游可能来自 `agentic-rethlas-proving`、`discover-math-problems`、`paper-to-skill`, +上游可能来自 `rethlas-proving`、`discover-math-problems`、`paper-to-skill`, 或用户自己的 Lean project。交接时应包含 intended theorem statement、allowed assumptions、 imports、当前 Lean errors/goals 和 proof blueprint。完成后返回 validated Lean patch、 minimized failure 或 blocked proof obligations;除非用户批准,不改变 theorem statement。 @@ -29,10 +29,10 @@ minimized failure 或 blocked proof obligations;除非用户批准,不改变 ```text AGENTS.md SKILL.md -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` -如果目标 agent 支持本地 Skill discovery,可以把 `skills/AI4Math-Lean-Agents/` +如果目标 agent 支持本地 Skill discovery,可以把 `skills/lean-formalization/` 安装或软链接到它的 Skill 路径,然后按需 reload 或 restart。Codex、Claude、 Gemini 和 OpenCode 的薄 adapter 分别见 `.codex/INSTALL.md`、`CLAUDE.md`、 `GEMINI.md` 和 `.opencode/INSTALL.md`。 @@ -45,7 +45,7 @@ Use this repository's Lean workflow. Read: - AGENTS.md - SKILL.md -- skills/AI4Math-Lean-Agents/SKILL.md +- skills/lean-formalization/SKILL.md Goal: <描述 Lean formalization、proof repair、theorem transcription 或 validation 任务> @@ -80,5 +80,5 @@ claim 前都应先问用户。 ## 维护者检查 ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` diff --git a/SKILL.md b/SKILL.md index 3a817a2..8714221 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,15 +1,15 @@ --- -name: ai4math-lean-agents +name: lean-formalization description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, Numina runtime setup, or local Lean validation. --- -# AI4Math Lean Agents +# Lean Formalization This root `SKILL.md` is a compatibility entrypoint for platforms that expect one top-level Skill file. The shared Skill layer lives at: ```text -skills/AI4Math-Lean-Agents/SKILL.md +skills/lean-formalization/SKILL.md ``` Read that concrete Skill before Lean work. Keep platform adapters thin and diff --git a/skills/AI4Math-Lean-Agents/SKILL.md b/skills/lean-formalization/SKILL.md similarity index 99% rename from skills/AI4Math-Lean-Agents/SKILL.md rename to skills/lean-formalization/SKILL.md index ff46aaf..297b36a 100644 --- a/skills/AI4Math-Lean-Agents/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -1,9 +1,9 @@ --- -name: ai4math-lean-agents +name: lean-formalization description: Use for interactive Lean 4 formal verification through the official Numina Lean Agent runtime, reusable Lean/mathlib workspaces, Numina deployment/calls, theorem formalization, proof repair, sorry completion, patch review, and minimal failure handoff. --- -# AI4Math Lean Agents +# Lean Formalization Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or a Lean Agent run. diff --git a/skills/AI4Math-Lean-Agents/agents/openai.yaml b/skills/lean-formalization/agents/openai.yaml similarity index 96% rename from skills/AI4Math-Lean-Agents/agents/openai.yaml rename to skills/lean-formalization/agents/openai.yaml index ee29cee..0dd3ba8 100644 --- a/skills/AI4Math-Lean-Agents/agents/openai.yaml +++ b/skills/lean-formalization/agents/openai.yaml @@ -1,3 +1,3 @@ -display_name: AI4Math Lean Agents +display_name: Lean Formalization short_description: Interactive Lean 4 verification through the official Numina Lean Agent runtime with reusable mathlib workspaces. default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。Lean Agent 默认指 Numina 官方 Lean Agent runtime,不要把 coding agent 重新定义成 Lean Agent。先检查 Numina readiness、共享 workspace、Claude/API 凭据和本地 Lean 验收能力,再推荐下一步。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。不要在 Numina 模式明确前说 API key 不需要。用户任务默认使用共享 Lean workspace;upstream Numina 示例只是 demo,可能 pin 不同 toolchain。一次最多问一个阻塞问题。coding agent 负责部署、配置、调用 Numina,并用本地 Lean/Lake 验收结果;direct Lean 只是验证或 fallback。 diff --git a/skills/AI4Math-Lean-Agents/config/env.example b/skills/lean-formalization/config/env.example similarity index 100% rename from skills/AI4Math-Lean-Agents/config/env.example rename to skills/lean-formalization/config/env.example diff --git a/skills/AI4Math-Lean-Agents/config/lean_agent.example.toml b/skills/lean-formalization/config/lean_agent.example.toml similarity index 100% rename from skills/AI4Math-Lean-Agents/config/lean_agent.example.toml rename to skills/lean-formalization/config/lean_agent.example.toml diff --git a/skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml b/skills/lean-formalization/config/numina_runtime.example.toml similarity index 100% rename from skills/AI4Math-Lean-Agents/config/numina_runtime.example.toml rename to skills/lean-formalization/config/numina_runtime.example.toml diff --git a/skills/AI4Math-Lean-Agents/examples/smoke/NuminaSmoke.lean b/skills/lean-formalization/examples/smoke/NuminaSmoke.lean similarity index 100% rename from skills/AI4Math-Lean-Agents/examples/smoke/NuminaSmoke.lean rename to skills/lean-formalization/examples/smoke/NuminaSmoke.lean diff --git a/skills/AI4Math-Lean-Agents/prompts/complete_sorries.md b/skills/lean-formalization/prompts/complete_sorries.md similarity index 100% rename from skills/AI4Math-Lean-Agents/prompts/complete_sorries.md rename to skills/lean-formalization/prompts/complete_sorries.md diff --git a/skills/AI4Math-Lean-Agents/prompts/formalize_statement.md b/skills/lean-formalization/prompts/formalize_statement.md similarity index 100% rename from skills/AI4Math-Lean-Agents/prompts/formalize_statement.md rename to skills/lean-formalization/prompts/formalize_statement.md diff --git a/skills/AI4Math-Lean-Agents/prompts/prove_theorem.md b/skills/lean-formalization/prompts/prove_theorem.md similarity index 100% rename from skills/AI4Math-Lean-Agents/prompts/prove_theorem.md rename to skills/lean-formalization/prompts/prove_theorem.md diff --git a/skills/AI4Math-Lean-Agents/prompts/repair_lean_file.md b/skills/lean-formalization/prompts/repair_lean_file.md similarity index 100% rename from skills/AI4Math-Lean-Agents/prompts/repair_lean_file.md rename to skills/lean-formalization/prompts/repair_lean_file.md diff --git a/skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md b/skills/lean-formalization/references/direct_lean_workflow.md similarity index 100% rename from skills/AI4Math-Lean-Agents/references/direct_lean_workflow.md rename to skills/lean-formalization/references/direct_lean_workflow.md diff --git a/skills/AI4Math-Lean-Agents/references/failure_taxonomy.md b/skills/lean-formalization/references/failure_taxonomy.md similarity index 100% rename from skills/AI4Math-Lean-Agents/references/failure_taxonomy.md rename to skills/lean-formalization/references/failure_taxonomy.md diff --git a/skills/AI4Math-Lean-Agents/references/interactive_orchestration.md b/skills/lean-formalization/references/interactive_orchestration.md similarity index 100% rename from skills/AI4Math-Lean-Agents/references/interactive_orchestration.md rename to skills/lean-formalization/references/interactive_orchestration.md diff --git a/skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md b/skills/lean-formalization/references/lean_runtime_configuration.md similarity index 100% rename from skills/AI4Math-Lean-Agents/references/lean_runtime_configuration.md rename to skills/lean-formalization/references/lean_runtime_configuration.md diff --git a/skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md b/skills/lean-formalization/references/numina_reverse_analysis.md similarity index 100% rename from skills/AI4Math-Lean-Agents/references/numina_reverse_analysis.md rename to skills/lean-formalization/references/numina_reverse_analysis.md diff --git a/skills/AI4Math-Lean-Agents/references/numina_runtime.md b/skills/lean-formalization/references/numina_runtime.md similarity index 100% rename from skills/AI4Math-Lean-Agents/references/numina_runtime.md rename to skills/lean-formalization/references/numina_runtime.md diff --git a/skills/AI4Math-Lean-Agents/references/review_checklist.md b/skills/lean-formalization/references/review_checklist.md similarity index 100% rename from skills/AI4Math-Lean-Agents/references/review_checklist.md rename to skills/lean-formalization/references/review_checklist.md diff --git a/skills/AI4Math-Lean-Agents/schemas/config.schema.json b/skills/lean-formalization/schemas/config.schema.json similarity index 100% rename from skills/AI4Math-Lean-Agents/schemas/config.schema.json rename to skills/lean-formalization/schemas/config.schema.json diff --git a/skills/AI4Math-Lean-Agents/schemas/result.schema.json b/skills/lean-formalization/schemas/result.schema.json similarity index 100% rename from skills/AI4Math-Lean-Agents/schemas/result.schema.json rename to skills/lean-formalization/schemas/result.schema.json diff --git a/skills/AI4Math-Lean-Agents/schemas/task.schema.json b/skills/lean-formalization/schemas/task.schema.json similarity index 100% rename from skills/AI4Math-Lean-Agents/schemas/task.schema.json rename to skills/lean-formalization/schemas/task.schema.json diff --git a/skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py b/skills/lean-formalization/scripts/ai4m_lean.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/ai4m_lean.py rename to skills/lean-formalization/scripts/ai4m_lean.py diff --git a/skills/AI4Math-Lean-Agents/scripts/check_lean_project.py b/skills/lean-formalization/scripts/check_lean_project.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/check_lean_project.py rename to skills/lean-formalization/scripts/check_lean_project.py diff --git a/skills/AI4Math-Lean-Agents/scripts/common.py b/skills/lean-formalization/scripts/common.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/common.py rename to skills/lean-formalization/scripts/common.py diff --git a/skills/AI4Math-Lean-Agents/scripts/configure_lean.py b/skills/lean-formalization/scripts/configure_lean.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/configure_lean.py rename to skills/lean-formalization/scripts/configure_lean.py diff --git a/skills/AI4Math-Lean-Agents/scripts/detect_sorry.py b/skills/lean-formalization/scripts/detect_sorry.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/detect_sorry.py rename to skills/lean-formalization/scripts/detect_sorry.py diff --git a/skills/AI4Math-Lean-Agents/scripts/direct_task.py b/skills/lean-formalization/scripts/direct_task.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/direct_task.py rename to skills/lean-formalization/scripts/direct_task.py diff --git a/skills/AI4Math-Lean-Agents/scripts/extract_minimal_failure.py b/skills/lean-formalization/scripts/extract_minimal_failure.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/extract_minimal_failure.py rename to skills/lean-formalization/scripts/extract_minimal_failure.py diff --git a/skills/AI4Math-Lean-Agents/scripts/numina_runtime.py b/skills/lean-formalization/scripts/numina_runtime.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/numina_runtime.py rename to skills/lean-formalization/scripts/numina_runtime.py diff --git a/skills/AI4Math-Lean-Agents/scripts/smoke_test.py b/skills/lean-formalization/scripts/smoke_test.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/smoke_test.py rename to skills/lean-formalization/scripts/smoke_test.py diff --git a/skills/AI4Math-Lean-Agents/scripts/tool_status.py b/skills/lean-formalization/scripts/tool_status.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/tool_status.py rename to skills/lean-formalization/scripts/tool_status.py diff --git a/skills/AI4Math-Lean-Agents/scripts/validate_patch.py b/skills/lean-formalization/scripts/validate_patch.py similarity index 100% rename from skills/AI4Math-Lean-Agents/scripts/validate_patch.py rename to skills/lean-formalization/scripts/validate_patch.py diff --git a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py similarity index 99% rename from skills/AI4Math-Lean-Agents/scripts/verify_delivery.py rename to skills/lean-formalization/scripts/verify_delivery.py index 71ae1e0..62d36d5 100644 --- a/skills/AI4Math-Lean-Agents/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -283,7 +283,7 @@ def verify( def main(argv: list[str] | None = None) -> None: - parser = argparse.ArgumentParser(description="Verify AI4Math Lean Agents delivery readiness") + parser = argparse.ArgumentParser(description="Verify Lean Formalization delivery readiness") parser.add_argument("--cwd", default=".") parser.add_argument("--require-environment", action="store_true") parser.add_argument("--include-workspace-build", action="store_true") diff --git a/skills/AI4Math-Lean-Agents/tests/fixtures/after_bad.lean b/skills/lean-formalization/tests/fixtures/after_bad.lean similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/fixtures/after_bad.lean rename to skills/lean-formalization/tests/fixtures/after_bad.lean diff --git a/skills/AI4Math-Lean-Agents/tests/fixtures/after_statement_changed.lean b/skills/lean-formalization/tests/fixtures/after_statement_changed.lean similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/fixtures/after_statement_changed.lean rename to skills/lean-formalization/tests/fixtures/after_statement_changed.lean diff --git a/skills/AI4Math-Lean-Agents/tests/fixtures/before.lean b/skills/lean-formalization/tests/fixtures/before.lean similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/fixtures/before.lean rename to skills/lean-formalization/tests/fixtures/before.lean diff --git a/skills/AI4Math-Lean-Agents/tests/fixtures/failure.lean b/skills/lean-formalization/tests/fixtures/failure.lean similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/fixtures/failure.lean rename to skills/lean-formalization/tests/fixtures/failure.lean diff --git a/skills/AI4Math-Lean-Agents/tests/test_check_lean_project.py b/skills/lean-formalization/tests/test_check_lean_project.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_check_lean_project.py rename to skills/lean-formalization/tests/test_check_lean_project.py diff --git a/skills/AI4Math-Lean-Agents/tests/test_cli.py b/skills/lean-formalization/tests/test_cli.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_cli.py rename to skills/lean-formalization/tests/test_cli.py diff --git a/skills/AI4Math-Lean-Agents/tests/test_common_config.py b/skills/lean-formalization/tests/test_common_config.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_common_config.py rename to skills/lean-formalization/tests/test_common_config.py diff --git a/skills/AI4Math-Lean-Agents/tests/test_configure_lean.py b/skills/lean-formalization/tests/test_configure_lean.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_configure_lean.py rename to skills/lean-formalization/tests/test_configure_lean.py diff --git a/skills/AI4Math-Lean-Agents/tests/test_detect_sorry.py b/skills/lean-formalization/tests/test_detect_sorry.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_detect_sorry.py rename to skills/lean-formalization/tests/test_detect_sorry.py diff --git a/skills/AI4Math-Lean-Agents/tests/test_direct_task.py b/skills/lean-formalization/tests/test_direct_task.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_direct_task.py rename to skills/lean-formalization/tests/test_direct_task.py diff --git a/skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py b/skills/lean-formalization/tests/test_numina_runtime.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_numina_runtime.py rename to skills/lean-formalization/tests/test_numina_runtime.py diff --git a/skills/AI4Math-Lean-Agents/tests/test_validate_patch.py b/skills/lean-formalization/tests/test_validate_patch.py similarity index 100% rename from skills/AI4Math-Lean-Agents/tests/test_validate_patch.py rename to skills/lean-formalization/tests/test_validate_patch.py From b943b815e3dea1e5cd50ac8f2e3647a49c1fe885 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 19 Jun 2026 11:05:56 +0800 Subject: [PATCH 23/37] Refine standalone README --- README.md | 24 ++++++++++-------------- README.zh-CN.md | 21 +++++++-------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 81d387c..08cfd26 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ verification with coding agents. The default Lean Agent path orchestrates the official Numina Lean Agent runtime; local Lean editing is the validation and fallback path when Numina is unavailable, declined, or insufficient. The bundled CLI is only a deterministic helper toolbox for environment checks, Lean -validation, Numina readiness/setup, patch review, and minimal failure handoff. +validation, Numina readiness/setup, patch review, and minimal failure extraction. The canonical skill package lives at: @@ -15,24 +15,20 @@ The canonical skill package lives at: skills/lean-formalization/ ``` -## AI4Math Role +## What This Skill Does -This skill is the Lean 4 formalization and proof-repair layer in the AI4Math -stack. Use it when a theorem statement, proof obligation, or generated proof -candidate needs machine-checked Lean evidence rather than informal proof review. +This standalone skill helps a coding agent work with Lean 4 formalization tasks: +inspect a Lean project, transcribe theorem statements, repair proofs, complete +`sorry`s when appropriate, review patches for unsafe proof shortcuts, and record +machine-checking evidence or a minimized failure. -## Handoff - -Upstream inputs may come from `rethlas-proving`, -`discover-math-problems`, `paper-to-skill`, or a user Lean project. Handoff -artifacts should include the intended theorem statement, allowed assumptions, -imports, current Lean errors or goals, and any proof blueprint. Return validated -Lean patches, minimized failures, or blocked proof obligations without changing -the theorem statement unless the user approves. +Use it directly with a Lean project, a Lean file, or a theorem statement that you +want the agent to formalize or validate. ## Installation / Loading -Use the repository checkout first. Ask your coding agent to read: +Clone or open this skill repository in your coding-agent environment. Then ask +your coding agent to read: ```text AGENTS.md diff --git a/README.zh-CN.md b/README.zh-CN.md index 1ab22d3..c718c5a 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,29 +2,22 @@ [English](README.md) | 简体中文 -本中文 README 聚焦安装、交互和 AI4Math 角色;完整 helper 和 validation 细节见英文 README。 - Lean Formalization 是一个面向 Lean 4 形式化验证的 guidance-first Skill package。默认 Lean Agent 路径是编排官方 Numina Lean Agent runtime;当 Numina 不可用、 用户拒绝或结果不足时,本地 Lean 编辑才是 validation 和 fallback 路径。附带 CLI 只是用于 -环境检查、Lean validation、Numina readiness/setup、patch review 和最小失败交接的确定性辅助工具。 - -## AI4Math 角色 +环境检查、Lean validation、Numina readiness/setup、patch review 和最小失败抽取的确定性辅助工具。 -这个 Skill 是 AI4Math 体系里的 Lean 4 形式化和 proof repair 层。当 theorem statement、 -proof obligation 或生成的 proof candidate 需要机器检查的 Lean 证据,而不是只做非形式化 -proof review 时,使用它。 +## 这个 Skill 做什么 -## 交接 +这个独立 Skill 帮助 coding agent 处理 Lean 4 形式化任务:检查 Lean project,转写 theorem statement, +修复 proof,必要时完成 `sorry`,检查 patch 中不安全的 proof shortcut,并记录 machine-checking evidence +或最小失败片段。 -上游可能来自 `rethlas-proving`、`discover-math-problems`、`paper-to-skill`, -或用户自己的 Lean project。交接时应包含 intended theorem statement、allowed assumptions、 -imports、当前 Lean errors/goals 和 proof blueprint。完成后返回 validated Lean patch、 -minimized failure 或 blocked proof obligations;除非用户批准,不改变 theorem statement。 +当你有 Lean project、Lean 文件,或希望 agent 形式化/验证的 theorem statement 时,可以直接使用它。 ## 安装 / 加载 -优先从当前仓库 checkout 使用。让 coding agent 读取: +在你的 coding-agent 环境里 clone 或打开这个 skill 仓库,然后让 coding agent 读取: ```text AGENTS.md From 34c86bd7fd6999d0a712f96b96086ce0535e85fa Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 19 Jun 2026 11:10:44 +0800 Subject: [PATCH 24/37] Add agent install guide --- .agent.md | 28 ++++++++++++++++++++++++++++ README.md | 23 +++++++---------------- README.zh-CN.md | 13 +++++-------- 3 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 .agent.md diff --git a/.agent.md b/.agent.md new file mode 100644 index 0000000..09107cd --- /dev/null +++ b/.agent.md @@ -0,0 +1,28 @@ +# lean-formalization Coding Agent Install Guide + +Use this file when a coding agent is asked to install `lean-formalization` interactively. +The shared Skill layer is the source of truth; platform adapters should only +help the active agent find and load that Skill layer. + +## Source + +- Repository: https://github.com/VeryMath/AI4Math-Lean-Agents.git +- Branch: `feature/numina-runtime-delivery` +- Skill entrypoint: `skills/lean-formalization/SKILL.md` +- This skill is standalone. Do not require the user to clone + `AI4Math-Skill-Library` just to use it. + +## Interactive Install Flow + +1. Accept either a repository URL/branch or a local folder from the user. +2. If the source is remote, clone or fetch the requested branch into an + appropriate workspace. If the source is local, use that folder directly. +3. Inspect `AGENTS.md`, `SKILL.md`, and the declared Skill entrypoint before + changing any configuration. +4. Detect the active coding-agent environment and its skill/config location. +5. Install or link the smallest directory that exposes the intended `SKILL.md`. + Preserve existing configuration and do not overwrite unrelated files. +6. Do not write API keys, tokens, or private credentials into repository files. +7. Reload or restart the target agent only when its discovery mechanism requires + it, then verify that `$lean-formalization` is discoverable. +8. Report the installed source, entrypoint, verification result, and any restart still required. diff --git a/README.md b/README.md index 08cfd26..9483afa 100644 --- a/README.md +++ b/README.md @@ -27,26 +27,17 @@ want the agent to formalize or validate. ## Installation / Loading -Clone or open this skill repository in your coding-agent environment. Then ask -your coding agent to read: +### One-line Agent Install + +Copy this to your coding agent: ```text -AGENTS.md -SKILL.md -skills/lean-formalization/SKILL.md +Please install the `lean-formalization` skill from https://github.com/VeryMath/AI4Math-Lean-Agents.git (branch: feature/numina-runtime-delivery). Read `.agent.md`, install the declared Skill entrypoint, verify that `$lean-formalization` is discoverable, and tell me whether I need to restart the agent. ``` -If your agent supports local Skill discovery, install or link -`skills/lean-formalization/` into that agent's Skill path and reload the agent -if needed. Platform notes live in `CLAUDE.md`, `GEMINI.md`, -`.codex/INSTALL.md`, and `.opencode/INSTALL.md`. - -Codex-style local install example: - -```bash -mkdir -p ~/.codex/skills -rsync -a --delete skills/lean-formalization/ ~/.codex/skills/lean-formalization/ -``` +If you already have this skill repository locally, replace the repository URL +with the local folder path. The coding agent should handle cloning, linking, +configuration, reload/restart checks, and verification. ## Quick Start diff --git a/README.zh-CN.md b/README.zh-CN.md index c718c5a..7b1263e 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -17,18 +17,15 @@ package。默认 Lean Agent 路径是编排官方 Numina Lean Agent runtime; ## 安装 / 加载 -在你的 coding-agent 环境里 clone 或打开这个 skill 仓库,然后让 coding agent 读取: +### 一句话安装 + +把下面这句话发给你的 coding agent: ```text -AGENTS.md -SKILL.md -skills/lean-formalization/SKILL.md +请帮我安装 `lean-formalization` skill,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git,分支:feature/numina-runtime-delivery。请读取 `.agent.md`,安装其中声明的 Skill entrypoint,验证 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 ``` -如果目标 agent 支持本地 Skill discovery,可以把 `skills/lean-formalization/` -安装或软链接到它的 Skill 路径,然后按需 reload 或 restart。Codex、Claude、 -Gemini 和 OpenCode 的薄 adapter 分别见 `.codex/INSTALL.md`、`CLAUDE.md`、 -`GEMINI.md` 和 `.opencode/INSTALL.md`。 +如果你已经有这个 skill 仓库的本地文件夹,把链接换成本地路径即可。clone、link、配置、reload/restart 检查和验证都交给 coding agent 处理。 ## 快速开始 From 2b16023b72bd9da6aa675c36e63198603d7879f6 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 19 Jun 2026 11:21:13 +0800 Subject: [PATCH 25/37] Refine README guide structure --- README.md | 30 ++++++++++-------------------- README.zh-CN.md | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 9483afa..fb11cb1 100644 --- a/README.md +++ b/README.md @@ -2,32 +2,22 @@ Chinese guide: [README.zh-CN.md](README.zh-CN.md) -Lean Formalization is a guidance-first skill package for Lean 4 formal -verification with coding agents. The default Lean Agent path orchestrates the -official Numina Lean Agent runtime; local Lean editing is the validation and -fallback path when Numina is unavailable, declined, or insufficient. The bundled -CLI is only a deterministic helper toolbox for environment checks, Lean -validation, Numina readiness/setup, patch review, and minimal failure extraction. +`lean-formalization` helps a coding agent work with Lean 4 formalization, proof repair, and validation tasks. -The canonical skill package lives at: +## When To Use It -```text -skills/lean-formalization/ -``` - -## What This Skill Does +Use this skill when you have: -This standalone skill helps a coding agent work with Lean 4 formalization tasks: -inspect a Lean project, transcribe theorem statements, repair proofs, complete -`sorry`s when appropriate, review patches for unsafe proof shortcuts, and record -machine-checking evidence or a minimized failure. +- a Lean project or Lean file that needs inspection; +- a theorem statement to transcribe or formalize; +- a proof with `sorry`, `admit`, errors, or statement drift risk; +- a need for optional Numina setup mediated by the coding agent. -Use it directly with a Lean project, a Lean file, or a theorem statement that you -want the agent to formalize or validate. +## What It Produces -## Installation / Loading +The agent should produce Lean patches, validation summaries, blocked-goal explanations, minimized failures, and optional Numina setup evidence. -### One-line Agent Install +## Installation Copy this to your coding agent: diff --git a/README.zh-CN.md b/README.zh-CN.md index 7b1263e..f10ec87 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,22 +2,22 @@ [English](README.md) | 简体中文 -Lean Formalization 是一个面向 Lean 4 形式化验证的 guidance-first Skill -package。默认 Lean Agent 路径是编排官方 Numina Lean Agent runtime;当 Numina 不可用、 -用户拒绝或结果不足时,本地 Lean 编辑才是 validation 和 fallback 路径。附带 CLI 只是用于 -环境检查、Lean validation、Numina readiness/setup、patch review 和最小失败抽取的确定性辅助工具。 +`lean-formalization` 帮助 coding agent 处理 Lean 4 形式化、proof repair 和 validation 任务。 -## 这个 Skill 做什么 +## 适合什么任务 -这个独立 Skill 帮助 coding agent 处理 Lean 4 形式化任务:检查 Lean project,转写 theorem statement, -修复 proof,必要时完成 `sorry`,检查 patch 中不安全的 proof shortcut,并记录 machine-checking evidence -或最小失败片段。 +当你有这些输入或需求时使用: -当你有 Lean project、Lean 文件,或希望 agent 形式化/验证的 theorem statement 时,可以直接使用它。 +- 需要检查的 Lean project 或 Lean 文件; +- 需要转写或形式化的 theorem statement; +- 带有 `sorry`、`admit`、errors 或 statement drift 风险的 proof; +- 需要由 coding agent 协调的可选 Numina 设置。 -## 安装 / 加载 +## 会产出什么 -### 一句话安装 +Agent 应产出 Lean patches、validation summaries、blocked-goal explanations、minimized failures 和可选 Numina setup evidence。 + +## 安装 把下面这句话发给你的 coding agent: From 064c6bddf4025b4100f5197e8085d09c96515ea3 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 12:50:13 +0800 Subject: [PATCH 26/37] Reframe Lean skill as coding-agent first --- .cursor/rules/lean-formalization.mdc | 4 +- .opencode/agents/lean-formalization.md | 12 +-- AGENTS.md | 10 +-- CLAUDE.md | 8 +- GEMINI.md | 8 +- skills/lean-formalization/SKILL.md | 46 ++++++----- skills/lean-formalization/agents/openai.yaml | 4 +- .../config/lean_agent.example.toml | 4 +- .../references/direct_lean_workflow.md | 10 +-- .../references/interactive_orchestration.md | 26 ++++--- .../references/lean_runtime_configuration.md | 10 +-- .../references/numina_reverse_analysis.md | 34 ++++---- .../references/numina_runtime.md | 12 +-- .../numina_subagent_troubleshooting.md | 77 +++++++++++++++++++ .../schemas/task.schema.json | 4 +- .../lean-formalization/scripts/ai4m_lean.py | 8 +- .../scripts/configure_lean.py | 12 +-- .../lean-formalization/scripts/direct_task.py | 16 ++-- .../lean-formalization/scripts/smoke_test.py | 6 +- .../lean-formalization/scripts/tool_status.py | 2 +- .../scripts/verify_delivery.py | 30 ++++---- skills/lean-formalization/tests/test_cli.py | 8 +- .../tests/test_common_config.py | 4 +- .../tests/test_configure_lean.py | 13 ++-- .../tests/test_direct_task.py | 13 ++-- 25 files changed, 235 insertions(+), 146 deletions(-) create mode 100644 skills/lean-formalization/references/numina_subagent_troubleshooting.md diff --git a/.cursor/rules/lean-formalization.mdc b/.cursor/rules/lean-formalization.mdc index cb681c2..853cdb8 100644 --- a/.cursor/rules/lean-formalization.mdc +++ b/.cursor/rules/lean-formalization.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/lean-formalization/SKILL.md` as the canonical workflow. -In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation; direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/lean-formalization/scripts/` is optional and should be used only for environment checks, structured validation, Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker: read/edit Lean, run Lean/Lake, iterate from errors, and validate final patches locally. Official Numina is an optional deployable subagent backend; preserve that deployment/call path but do not make it the default. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/lean-formalization/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. -Deploy or call the official Numina runtime only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. +Deploy or call the official Numina subagent only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.opencode/agents/lean-formalization.md b/.opencode/agents/lean-formalization.md index f18e48e..e290655 100644 --- a/.opencode/agents/lean-formalization.md +++ b/.opencode/agents/lean-formalization.md @@ -10,18 +10,18 @@ skills/lean-formalization/SKILL.md Rules: -- In this skill, Lean Agent means the official Numina Lean Agent runtime. -- Orchestrate Numina deployment, configuration, invocation, and local Lean validation. -- Use direct Lean editing as validation or fallback, not as the default Lean Agent mode. +- This is a coding-agent-first Lean skill. +- The coding agent is the primary Lean worker: read/edit Lean, run Lean/Lake, iterate from errors, and validate final patches locally. +- Official Numina is an optional deployable subagent backend; preserve the deployment/call path but do not make it the default. - Match the user's language by default. If the user's language is ambiguous, default to Chinese. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. - Use the bundled smoke test when no user target is available. -- Opening readiness should inspect Numina readiness before recommending work. -- Do not say API keys are unnecessary until the Numina mode is clear. +- Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. +- Do not require API keys for the default coding-agent path. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. - Validate with Lean/Lake after meaningful edits. - Use helper CLI commands only as deterministic guardrails. -- Use official Numina through the approved human-in-the-loop runtime flow. +- Use official Numina through the approved human-in-the-loop subagent workflow. - Preserve theorem statements unless the user explicitly approves a change. diff --git a/AGENTS.md b/AGENTS.md index 7e9284b..3ccfee0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,17 +4,17 @@ Use the canonical shared Skill layer at `skills/lean-formalization/SKILL.md` for Core rules: -- In this skill, Lean Agent means the official Numina Lean Agent runtime. -- The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation. -- Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. +- This is a coding-agent-first Lean skill. +- The coding agent is the primary Lean worker. +- Official Numina is an optional deployable subagent backend. - Match the user's language by default. - If the user's language is ambiguous, default to Chinese. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. - Use the bundled smoke test when no user target is available. -- Opening readiness should inspect Numina readiness before recommending work. -- Do not say API keys are unnecessary until the Numina mode is clear. +- Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. +- Do not require API keys for the default coding-agent path. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. - Prefer the user's existing Lake project. Use the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` only when a standalone file needs project context. - Preserve theorem statements unless the user explicitly approves a change. diff --git a/CLAUDE.md b/CLAUDE.md index 6aac3bc..e6d3af1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,15 +6,15 @@ For Lean work in this repository, read and follow the shared Skill layer: skills/lean-formalization/SKILL.md ``` -Use Claude Code as the Numina orchestrator and local Lean validator. In this skill, Lean Agent means the official Numina Lean Agent runtime. Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. +Use Claude Code as the primary Lean coding agent. Official Numina is an optional deployable subagent backend; preserve that setup/call path but do not make it the default. Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Use the bundled smoke test when no user target is available. -Opening readiness should inspect Numina readiness before recommending work. -Do not say API keys are unnecessary until the Numina mode is clear. +Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. +Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -Deploy or call the official Numina runtime only after explanation and approval. Keep secrets in environment variables or ignored local files. +Deploy or call the official Numina subagent runtime only after explanation and approval. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index 297f5e8..5cb7a79 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -6,15 +6,15 @@ For Lean 4 formal verification tasks, use the shared Skill layer at: skills/lean-formalization/SKILL.md ``` -In this skill, Lean Agent means the official Numina Lean Agent runtime. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation. Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. +Use Gemini as the primary Lean coding agent. Official Numina is an optional deployable subagent backend; preserve that setup/call path but do not make it the default. Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Use the bundled smoke test when no user target is available. -Opening readiness should inspect Numina readiness before recommending work. -Do not say API keys are unnecessary until the Numina mode is clear. +Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. +Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -The helper CLI under `skills/lean-formalization/scripts/` is optional tooling. It can report and configure the official Numina runtime, but the agent should still validate final Lean patches locally. +The helper CLI under `skills/lean-formalization/scripts/` is optional tooling. It can report and configure the official Numina subagent runtime, but the agent should still validate final Lean patches locally. diff --git a/skills/lean-formalization/SKILL.md b/skills/lean-formalization/SKILL.md index 297b36a..29afaab 100644 --- a/skills/lean-formalization/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -1,40 +1,42 @@ --- name: lean-formalization -description: Use for interactive Lean 4 formal verification through the official Numina Lean Agent runtime, reusable Lean/mathlib workspaces, Numina deployment/calls, theorem formalization, proof repair, sorry completion, patch review, and minimal failure handoff. +description: Use for interactive Lean 4 formal verification by coding agents with reusable Lean/mathlib workspaces, theorem formalization, proof repair, sorry completion, patch review, optional official Numina subagent deployment/calls, and minimal failure handoff. --- # Lean Formalization -Use this skill when the user wants Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or a Lean Agent run. +Use this skill when the user wants a coding agent to do Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or optional official Numina Lean Agent/subagent work. -In this skill, Lean Agent means the official Numina Lean Agent runtime. Default execution mode is Numina Agent mode. The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation. Do not redefine Lean Agent as the coding agent. +This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker. It reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, preserves theorem statements, and iterates with the user. Default execution mode is coding-agent mode. + +Official Numina is an optional deployable subagent backend. Keep the official Numina deployment/call path available for users who ask for the official Lean Agent, batch proof search, or an external subagent run. Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run. Match the user's language by default. If the user's language is ambiguous, default to Chinese. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. A language switch is not a task reset. Keep the current environment state, prior diagnosis, and recommended next action, then continue leading in the new language. Lead the interaction; do not wait for the user to drive every step. When the user's request is broad or underspecified, first orient yourself to the Lean project/workspace state, then propose the next useful action in plain language. Do not open with a passive "send me the file" checklist when you can inspect context or offer a concrete starting path. -If no target is available, run or propose a safe local smoke/readiness check. Use the bundled smoke test when no user target is available. Then recommend a default path, such as checking Numina readiness, preparing the shared workspace as Numina's target project, or running the built-in smoke theorem before an official Numina call. Avoid ending with only "send me a file" or an equivalent passive handoff. +If no target is available, run or propose a safe local smoke/readiness check. Use the bundled smoke test when no user target is available. Then recommend a default path, such as checking the shared Lean workspace, running the built-in smoke theorem, inspecting a Lean project, or checking Numina subagent readiness if the user wants that path. Avoid ending with only "send me a file" or an equivalent passive handoff. -The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, `rg`, Lean/Lake validation, repository context, and the official Numina runner. Use helper commands only when their deterministic output is useful. +The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake validation, and repository context. Use helper commands only when their deterministic output is useful. -Use official Numina through a human-in-the-loop runtime workflow. Numina lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. +Use official Numina through a human-in-the-loop subagent workflow. Numina lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, proxy/MCP, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. -Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. +Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. Use it to check the shared workspace, validate Numina output, reduce failures, or continue locally only when the user declines or cannot use Numina. +Do not remove the official Numina subagent path. Treat it as an optional backend with explicit approval, while keeping the direct coding-agent Lean workflow useful without external APIs. ## Agent Playbook -1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, Numina runtime, and Numina credentials/auth, and summarize what is already usable. Treat upstream Numina example projects as demos only; do not let their pinned `lean-toolchain` make the shared workspace look broken. -2. If the user has not provided a precise target, offer a small next-step menu such as configure Numina credentials, run a Numina readiness check, prepare the shared workspace as a Numina target, formalize a natural-language/LaTeX theorem through Numina, repair an existing Lean file through Numina, or inspect a Lean project. Recommend one default path based on what inspection found. +1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, local Lean validation readiness, Numina runtime, and Numina credentials/auth, and summarize what is already usable. Treat upstream Numina example projects as demos only; do not let their pinned `lean-toolchain` make the shared workspace look broken. +2. If the user has not provided a precise target, offer a small next-step menu such as run the bundled smoke test, repair an existing Lean file, formalize a natural-language/LaTeX theorem, inspect a Lean project, configure Numina credentials, run a Numina readiness check, or prepare the shared workspace as a Numina target. Recommend one default path based on what inspection found. 3. Ask at most one blocking question at a time. Prefer a concrete recommendation plus one decision question over a list of required inputs. -4. Understand the user's intent: configure Numina, call Numina, repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. -5. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available; otherwise use the shared workspace as Numina's target project. +4. Understand the user's intent: direct coding-agent repair/formalization, configure Numina, call Numina, repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. +5. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available; otherwise use the shared workspace as the coding-agent project context and optional Numina target project. 6. For standalone files, use or create the shared workspace `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`; do not create a second project-local workspace unless the user asks for isolation. -7. When reporting readiness, lead with Numina readiness, then local Lean validation readiness. If Numina credentials are missing, say that Numina calls need configuration instead of implying the skill can proceed as the expected Lean Agent. -8. Before a Numina setup or run, inspect `doctor` readiness, explain the deployment/call, target project, prompt, result directory, credential state, and local validation plan; proceed only after approval. +7. When reporting readiness, lead with local Lean readiness, then Numina subagent readiness. If Numina credentials are missing, say that only the optional Numina subagent path needs configuration. +8. Before a Numina setup or run, inspect `doctor` readiness, explain the deployment/call, target project, prompt, result directory, credential/proxy/MCP state, and local validation plan; proceed only after approval. 9. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -10. Call the official Numina runner for proof search/formalization when approved. After Numina changes Lean files, run Lean/Lake validation and patch safety checks before accepting results. +10. Edit Lean directly in small steps for the default coding-agent path. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. 11. Preserve theorem statements unless the user explicitly approves a change. 12. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. 13. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. @@ -43,38 +45,40 @@ Direct Lean editing is a validation and fallback path, not the default Lean Agen Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk: -- `env` / `doctor`: inspect Lean workspace, local tool availability, and Numina readiness. +- `env` / `doctor`: inspect Lean workspace, local tool availability, and Numina subagent readiness. - `configure --create-workspace`: create or reuse the shared managed workspace. - `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`. - `smoke-test`: run the bundled `examples/smoke/NuminaSmoke.lean` target in the shared workspace without external API calls. - `check`: run a structured Lean/Lake validation. - `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. - `minimize-failure`: extract a compact failing Lean fragment. -- `prove` / `formalize` / `repair` / `complete-sorries` / `batch`: optional dry-run task envelopes for bookkeeping; prefer the official Numina runner for actual Lean Agent proof search. +- `prove` / `formalize` / `repair` / `complete-sorries` / `batch`: optional dry-run task envelopes for coding-agent bookkeeping; use the official Numina runner only when the optional subagent path is approved. - `verify-delivery`: validate this skill package. All helper commands emit machine-readable JSON on stdout. Human-readable diagnostics go to stderr or log files. ## Numina Runtime -When using the official Numina runtime, follow `references/numina_runtime.md`. Proof strategy is a human-in-the-loop process with the user, the coding agent, local Lean checks, and the official Numina runner as the default Lean Agent. +When using the official Numina runtime, follow `references/numina_runtime.md`. For auth/proxy/MCP/failure triage, follow `references/numina_subagent_troubleshooting.md`. Proof strategy is a human-in-the-loop process with the user, the coding agent, local Lean checks, and, when approved, the official Numina runner as an optional subagent backend. ## Safety Rules - Do not call external model APIs or mutate Numina runtime state without approval. -- If the user asks for the Lean Agent, treat that as Numina and explain any needed credentials/setup directly. +- If the user asks for the official Lean Agent, Numina, batch proof search, or external subagent, explain needed credentials/setup directly. - Do not commit local machine-specific paths. - Do not call external APIs during `env`, `doctor`, `check`, `review`, `detect-sorry`, tests, or dry-runs. - Do not store secrets in tracked files; use environment variables or `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/.env.local`. - Do not accept final Lean patches containing `sorry`, `admit`, or newly introduced `axiom`. - Do not silently weaken theorem statements or change existing project versions. -- Do not let helper command availability override the official Numina Agent path when the user expects Lean Agent behavior. +- Do not let helper command availability override a better coding-agent path. +- Do not remove the official Numina subagent path. ## References -- Read `references/direct_lean_workflow.md` for local Lean validation and fallback repair guidance. +- Read `references/direct_lean_workflow.md` for the default coding-agent proof/repair/formalization loop. - Read `references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. - Read `references/numina_runtime.md` when the user wants the official Numina deployment/call path. +- Read `references/numina_subagent_troubleshooting.md` when Numina auth, proxy, MCP, or runner failures appear. - Read `references/interactive_orchestration.md` when guiding user intake and task decomposition. - Read `references/review_checklist.md` before accepting a Lean patch. - Read `references/failure_taxonomy.md` when reporting a blocked proof. diff --git a/skills/lean-formalization/agents/openai.yaml b/skills/lean-formalization/agents/openai.yaml index 0dd3ba8..dc0c37f 100644 --- a/skills/lean-formalization/agents/openai.yaml +++ b/skills/lean-formalization/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: Lean Formalization -short_description: Interactive Lean 4 verification through the official Numina Lean Agent runtime with reusable mathlib workspaces. -default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。Lean Agent 默认指 Numina 官方 Lean Agent runtime,不要把 coding agent 重新定义成 Lean Agent。先检查 Numina readiness、共享 workspace、Claude/API 凭据和本地 Lean 验收能力,再推荐下一步。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。不要在 Numina 模式明确前说 API key 不需要。用户任务默认使用共享 Lean workspace;upstream Numina 示例只是 demo,可能 pin 不同 toolchain。一次最多问一个阻塞问题。coding agent 负责部署、配置、调用 Numina,并用本地 Lean/Lake 验收结果;direct Lean 只是验证或 fallback。 +short_description: Interactive Lean 4 verification for coding agents with reusable mathlib workspaces and optional official Numina subagent calls. +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 diff --git a/skills/lean-formalization/config/lean_agent.example.toml b/skills/lean-formalization/config/lean_agent.example.toml index 0b28a7d..0a42f33 100644 --- a/skills/lean-formalization/config/lean_agent.example.toml +++ b/skills/lean-formalization/config/lean_agent.example.toml @@ -14,8 +14,8 @@ preferred_mathlib_rev = "auto" allow_user_project_version_changes = false [agent] -mode = "numina-agent" -backend = "official-numina" +mode = "coding-agent" +backend = "none" max_local_iterations = 5 require_user_statement_confirmation = true diff --git a/skills/lean-formalization/references/direct_lean_workflow.md b/skills/lean-formalization/references/direct_lean_workflow.md index 0107a63..15a14d7 100644 --- a/skills/lean-formalization/references/direct_lean_workflow.md +++ b/skills/lean-formalization/references/direct_lean_workflow.md @@ -1,15 +1,15 @@ -# Local Lean Validation and Fallback Workflow +# Direct Coding-Agent Lean Workflow -Direct Lean editing is a validation and fallback path, not the default Lean Agent mode. The default Lean Agent is the official Numina runtime; the coding agent uses local Lean/Lake to prepare targets, validate Numina output, minimize failures, and continue locally only when the user declines or cannot use Numina. +This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. ## Guidance-First Loop -1. Read the user's request and classify whether this is Numina setup, Numina call, output validation, or fallback local repair. +1. Read the user's request and classify whether this is repair, theorem formalization, proof completion, sorry completion, patch review, Numina setup/call, or output validation. 2. Inspect the target files, imports, nearby lemmas, and current Lean errors. 3. Choose the validation context: existing Lake project first, managed workspace only for standalone files. 4. For formalization, draft the Lean declaration and ask for confirmation before long proof work. 5. Make one small Lean edit at a time. -6. Run Lean/Lake validation after meaningful edits or Numina output, usually `lake env lean `, `lake build`, or the helper `check` command. +6. Run Lean/Lake validation after meaningful edits, usually `lake env lean `, `lake build`, or the helper `check` command. 7. Diagnose the first concrete Lean error or unsolved goal before changing strategy. 8. Add helper lemmas only when they reduce proof complexity and keep theorem statements unchanged. 9. Review the final patch with direct inspection and, when useful, `review` or `detect-sorry`. @@ -25,7 +25,7 @@ Use helpers for mechanical checks: - failure handoff: `minimize-failure`; - package QA: `verify-delivery`. -Do not route creative proof search through helper commands. `prove`, `formalize`, `repair`, `complete-sorries`, and `batch` only produce optional task envelopes for bookkeeping; the official Numina runner is the default Lean Agent for proof search/formalization. +Do not route creative proof search through helper commands. `prove`, `formalize`, `repair`, `complete-sorries`, and `batch` only produce optional task envelopes for bookkeeping. Use the official Numina runner only when the optional subagent path is approved. ## Workspace Choice diff --git a/skills/lean-formalization/references/interactive_orchestration.md b/skills/lean-formalization/references/interactive_orchestration.md index f0a2ec1..6cadee5 100644 --- a/skills/lean-formalization/references/interactive_orchestration.md +++ b/skills/lean-formalization/references/interactive_orchestration.md @@ -1,24 +1,24 @@ # Interactive Orchestration -The coordinating coding agent owns user interaction, Numina orchestration, and final validation. It delegates proof search/formalization to the official Numina Lean Agent by default when the user asks for the Lean Agent. +The coordinating coding agent owns user interaction, Lean proof/formalization work, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. -This reference covers the guidance layer: session opening, intake, task classification, Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. +This reference covers the guidance layer: session opening, intake, task classification, direct coding-agent Lean work, optional Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. ## Session Opening If the user's language is ambiguous, default to Chinese. The skill display name, repository name, or command name is not enough evidence to choose English. -In this skill, Lean Agent means the official Numina Lean Agent runtime. Default execution mode is Numina Agent mode. Do not redefine Lean Agent as the coding agent. +This is a coding-agent-first Lean skill. Official Numina is an optional deployable subagent backend. Lead the interaction; do not wait for the user to drive every step. On a broad request, first orient to the current state instead of asking for every input at once: - inspect whether the current directory is a Lake project; - check whether the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` exists; -- inspect Numina runtime, upstream checkout, tools, and credential/auth readiness; -- mention local Lean readiness as the validation layer; +- inspect local Lean/Lake readiness and shared workspace state; +- inspect Numina runtime, upstream checkout, tools, and credential/auth readiness separately; - say what can be done immediately and what would require confirmation. -Opening readiness should inspect Numina readiness before recommending work. Do not say API keys are unnecessary until the Numina mode is clear. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. +Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. When checking Numina, distinguish runtime readiness from upstream demo readiness. The runtime can be usable with the shared Lean workspace even if an upstream example or benchmark pins a different `lean-toolchain`. Report that as an example-project issue, not as a failure of the shared environment. @@ -28,12 +28,14 @@ If no target is available, run or propose a safe local smoke/readiness check. Us If no precise target is provided, offer a small menu and recommend one path. For example: +- run the bundled smoke test to verify the local Lean/mathlib validation layer; +- repair or complete an existing Lean file with the coding agent; +- formalize a natural-language or LaTeX theorem with the coding agent; +- inspect a Lean/Lake project and summarize readiness; - configure missing Numina credentials/auth; - run a Numina readiness check; -- run the bundled smoke test to verify the local Lean/mathlib validation layer; - prepare the shared workspace as the Numina target project; -- call Numina on a natural-language/LaTeX theorem or Lean file; -- inspect a Lean/Lake project and summarize whether Numina can target it. +- call Numina on a natural-language/LaTeX theorem or Lean file. Ask at most one blocking question at a time. A good opening ends with one decision question, not a checklist. @@ -52,13 +54,13 @@ Prefer asking these only after orientation. If the repository already reveals th ## Decomposition -Break large requests into small Lean targets that Numina can run against and that can be checked afterward with Lean/Lake commands or the helper `check` command. +Break large requests into small Lean targets that the coding agent can work on directly, and that Numina can run against if the optional subagent path is approved. Each target should be checkable afterward with Lean/Lake commands or the helper `check` command. For natural-language or LaTeX statements, draft the Lean declaration first and ask for confirmation before long proof work. Once the declaration is confirmed, treat statement preservation as a hard guardrail. ## Numina Run -Before an official Numina call, state the target project/file, prompt file, max rounds, result directory, credential state, and validation plan. Ask for approval before any external model call or runtime mutation. +Before an official Numina call, state the target project/file, prompt file, max rounds, result directory, credential/proxy/MCP state, and validation plan. Ask for approval before any external model call or runtime mutation. After Numina returns, inspect changed Lean files, run local Lean/Lake validation, and reject results containing `sorry`, `admit`, new `axiom`, or unapproved theorem statement changes. @@ -69,7 +71,7 @@ Stop when: - validation succeeds without `sorry`, `admit`, or new `axiom`; - max local iterations are reached; - Lean workspace setup is missing or broken; -- Numina credentials/auth are missing and the user has not approved fallback work; +- optional Numina credentials/auth are missing and the user specifically requires Numina; - the remaining error requires a human mathematical decision; - the only path forward would weaken the theorem statement without approval. diff --git a/skills/lean-formalization/references/lean_runtime_configuration.md b/skills/lean-formalization/references/lean_runtime_configuration.md index d373c72..f4cb8e3 100644 --- a/skills/lean-formalization/references/lean_runtime_configuration.md +++ b/skills/lean-formalization/references/lean_runtime_configuration.md @@ -1,6 +1,6 @@ # Lean Runtime Configuration -This skill uses the official Numina Lean Agent runtime by default. Local Lean/Lake is the validation layer and fallback repair path. Numina runtime state lives under ignored shared local state; see `numina_runtime.md` for deployment and call details. +This skill uses a coding-agent Lean workflow by default. Local Lean/Lake is the primary validation layer. Official Numina is an optional deployable subagent backend under ignored shared local state; see `numina_runtime.md` for deployment and call details. ## Shared Layout @@ -13,7 +13,7 @@ ${AI4MATH_HOME:-~/.ai4math}/ └── failures/ ``` -Repository-local machine settings still live under `/.ai4math/` and should not be committed. The reusable Lean workspace and Numina runtime are shared by default so standalone tasks do not create a fresh workspace in every project. +Repository-local machine settings still live under `/.ai4math/` and should not be committed. The reusable Lean workspace and optional Numina runtime are shared by default so standalone tasks do not create a fresh workspace in every project. ## Tool Checks @@ -24,7 +24,7 @@ python scripts/ai4m_lean.py doctor --cwd . python scripts/ai4m_lean.py env --cwd . ``` -Required local validation tools are `git`, `python3`, `elan`, `lean`, and `lake`. Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Official Numina calls need a working Claude CLI/auth path and may need additional API keys for search/tool skills. +Required default workflow tools are `git`, `python3`, `elan`, `lean`, and `lake`. Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Official Numina subagent calls need a working Claude CLI/auth path and may need additional API keys for search/tool skills. ## Reusable Lean Workspace @@ -57,8 +57,8 @@ align_workspace_versions = true preferred_toolchain = "auto" [agent] -mode = "numina-agent" -backend = "official-numina" +mode = "coding-agent" +backend = "none" ``` Environment overrides: diff --git a/skills/lean-formalization/references/numina_reverse_analysis.md b/skills/lean-formalization/references/numina_reverse_analysis.md index b4d6d6f..c7c0e3f 100644 --- a/skills/lean-formalization/references/numina_reverse_analysis.md +++ b/skills/lean-formalization/references/numina_reverse_analysis.md @@ -1,6 +1,6 @@ # Numina Reverse Analysis for AI4Math -This reference records how this skill delegates Lean Agent behavior to the public Numina Lean Agent workflow and keeps local Lean validation around it. For deployment/call instructions, use `numina_runtime.md`. +This reference records what this coding-agent Lean skill learns from the public Numina Lean Agent workflow, and which parts remain available through the optional official Numina subagent backend. For deployment/call instructions, use `numina_runtime.md`. ## Source Scope @@ -8,11 +8,11 @@ This reference records how this skill delegates Lean Agent behavior to the publi - Result repository: https://github.com/project-numina/Numina-Putnam2025 - Paper reference: https://arxiv.org/abs/2601.14027 -The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to call the official Numina runtime as the Lean Agent and use reusable AI4Math guardrails around setup, workspace choice, and validation. +The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to make coding agents better Lean workers while preserving a deployable path to the official Numina runtime when the user wants a subagent. ## Distilled Patterns -1. Use Numina as the Lean Agent for proof search/formalization. +1. Use a coding agent as the primary Lean worker, with Numina available as an optional subagent. 2. Keep Lean/Lake validation as the correctness oracle. 3. Treat theorem statement preservation as a first-class safety check. 4. Work in bounded rounds with a clear stopping condition. @@ -20,9 +20,9 @@ The goal is not to copy Numina prompts or reimplement Numina proof search. The g 6. When blocked, reduce the problem to the smallest useful failing Lean fragment. 7. Prefer reusable Lean workspaces so setup cost is not paid on every standalone problem. -## Runtime State +## Optional Runtime State -The default AI4Math Lean Agent loop expects these runtime dependencies for official Numina calls: +The default AI4Math coding-agent loop does not require these runtime dependencies, but the optional official Numina subagent path does: - upstream Numina repository checkout; - Numina Python environment; @@ -31,21 +31,23 @@ The default AI4Math Lean Agent loop expects these runtime dependencies for offic - API-key or login setup; - backend round streaming or benchmark execution. -Those concerns are handled by the official upstream checkout under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/` and the human-in-the-loop flow in `numina_runtime.md`. Local direct Lean work remains available only as validation or fallback. +Those concerns are handled by the official upstream checkout under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/` and the human-in-the-loop flow in `numina_runtime.md`. -## Numina-Orchestrated Workflow +## Coding-Agent-First Workflow ```mermaid flowchart TD A["User asks for Lean work"] --> B["Coding agent classifies task"] - B --> C["Inspect Numina runtime and Lean target project"] - C --> D["Call official Numina runner after approval"] - D --> E["Run local Lean/Lake check"] + B --> C["Inspect Lean project or shared workspace"] + C --> D["Coding agent edits Lean directly"] + D --> E["Run Lean/Lake check"] E --> F{"Verified without unsafe placeholders?"} F -->|yes| G["Review patch and return result"] - F -->|no| H{"Useful local iteration remains?"} + F -->|no| H{"Use local iteration or approved Numina subagent?"} H -->|yes| D - H -->|no| I["Extract minimal failure and report exact errors/goals"] + H -->|Numina| N["Call official Numina subagent after approval"] + N --> E + H -->|blocked| I["Extract minimal failure and report exact errors/goals"] ``` ## AI4Math Skill Mapping @@ -53,7 +55,7 @@ flowchart TD | Numina idea | AI4Math implementation | | --- | --- | | Environment gate before proof attempts | `env`, `doctor`, `configure`, `check` | -| Official runner invocation | `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` with documented Numina commands | +| Official runner invocation | Optional `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` with documented Numina commands | | Bounded proof rounds | `max_local_iterations` / `max_rounds` | | Statement drift guard | `validate_patch.py` | | Placeholder guard | `detect_sorry.py` and `review` | @@ -71,8 +73,8 @@ flowchart TD If a future agent reads this file during normal Lean work, the default action item is: -1. verify Numina runtime/auth readiness; +1. verify local Lean readiness; 2. prepare the target in the user's Lake project or shared workspace; -3. explain and call the official Numina runner after approval; -4. validate resulting Lean changes locally; +3. edit/check directly as a coding agent; +4. use official Numina only if the user asks for the subagent path or it is approved; 5. return a verified patch or minimal failure. diff --git a/skills/lean-formalization/references/numina_runtime.md b/skills/lean-formalization/references/numina_runtime.md index 1def3b2..6052384 100644 --- a/skills/lean-formalization/references/numina_runtime.md +++ b/skills/lean-formalization/references/numina_runtime.md @@ -1,14 +1,14 @@ -# Official Numina Lean Agent Runtime +# Optional Official Numina Subagent Runtime -This skill treats the official `project-numina/numina-lean-agent` repository as the default Lean Agent. The coding agent manages setup, calls, user approvals, and final Lean validation. +This skill keeps the official `project-numina/numina-lean-agent` repository as an optional deployable subagent backend. The default path is coding-agent Lean work with local Lean/Lake validation; Numina is used when the user asks for the official Lean Agent, batch proof search, or an external subagent run. ## Agent Flow -1. Clarify the target: configure Numina, call Numina on a Lean project/file/folder, or validate Numina output. +1. Clarify the target: configure Numina, call Numina on a Lean project/file/folder, validate Numina output, or continue with the default coding-agent path. 2. Run `doctor --cwd .` when useful and read the `numina` readiness block before recommending a path. 3. Explain what setup may do: clone the official repository, run `tutorial/setup.sh`, install or use `elan`, `lake`, `curl`, `uv`, and `claude`, and require model/API credentials or Claude CLI auth for calls. 4. After approval, run `configure --cwd . --setup-numina --project-name `. Use `--dry-run` first when the user wants to review commands. -5. For an official Numina Agent run, call the upstream runner from `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. +5. For an official Numina subagent run, call the upstream runner from `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/upstream` using its documented interface, normally `uv run python -m scripts.run_claude from-folder --prompt-file prompts/autosearch/main_entry.md --max-rounds --result-dir `. 6. After Numina changes Lean files, use local `check`, `detect-sorry`, and `review` before accepting the patch. Default to the shared Lean workspace for user tasks. Upstream Numina examples or benchmarks may pin their own `lean-toolchain`; that only describes the example project, not the readiness of `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. @@ -26,10 +26,12 @@ Do not commit runtime state, API keys, generated results, or local machine paths Claude authentication can come from the user's normal Claude CLI login or environment variables such as `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`. Numina's CLI skills may also need `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, or `AXLE_API_KEY`. -If the user asks whether API keys are needed, answer from the Numina mode: official Numina calls need a working Claude CLI/auth path and may need additional keys for search/tool skills. Direct local Lean validation does not need API keys, but it is not the default Lean Agent mode. +If the user asks whether API keys are needed, distinguish the two paths: the default coding-agent Lean workflow and local Lean validation do not need API keys; official Numina subagent calls need a working Claude CLI/auth path and may need additional keys for search/tool skills. The helper readiness report redacts values and only reports whether keys appear configured. +For authentication, proxy, MCP scope, and runner failure triage, use `numina_subagent_troubleshooting.md`. + ## Boundary The AI4Math skill still owns delivery quality. Official Numina may propose or edit proofs, but final acceptance requires local Lean/Lake validation and the usual patch safety checks: no `sorry`, no `admit`, no newly introduced `axiom`, and no theorem statement drift unless explicitly approved. diff --git a/skills/lean-formalization/references/numina_subagent_troubleshooting.md b/skills/lean-formalization/references/numina_subagent_troubleshooting.md new file mode 100644 index 0000000..b239865 --- /dev/null +++ b/skills/lean-formalization/references/numina_subagent_troubleshooting.md @@ -0,0 +1,77 @@ +# Numina Subagent Troubleshooting + +Use this reference when the optional official Numina subagent path fails during setup, authentication, proxy routing, MCP/tool scope, runner execution, or Lean validation. Keep the default coding-agent Lean path available unless the user specifically requires Numina. + +## Checkpoint Format + +Report failures as: + +```text +[check] +[pass/fail] +[next action] +``` + +Do not expose API key values. Only report whether a credential appears configured. + +## Authentication Modes + +Mode A: Claude CLI or Anthropic-compatible environment. + +Required signals: + +- `claude` is installed and authenticated, or `ANTHROPIC_AUTH_TOKEN` is configured; +- `ANTHROPIC_BASE_URL` is set when using a non-default endpoint; +- `ANTHROPIC_MODEL` names the intended model. + +Mode B: Gemini or another provider through LiteLLM/Anthropic-compatible proxy. + +Required signals: + +- upstream key such as `GEMINI_API_KEY` is configured; +- LiteLLM or the team gateway is reachable; +- `ANTHROPIC_BASE_URL` points to the proxy; +- `ANTHROPIC_AUTH_TOKEN` is set to the proxy token expected by that gateway; +- a small `/v1/messages` probe succeeds before running Numina. + +## Proxy Checks + +When `ANTHROPIC_BASE_URL` is not the public Anthropic endpoint: + +- check that the base URL is reachable from the same shell that will run Numina; +- verify proxy logs if the request reaches the proxy but model routing fails; +- separate network failure from model-auth failure. + +Typical next actions: + +- proxy unreachable: start LiteLLM or fix `ANTHROPIC_BASE_URL`; +- `401` or auth error: refresh token/key and rerun readiness; +- model not found: align `ANTHROPIC_MODEL` with the proxy route. + +## MCP Scope + +If the official runner or Claude CLI tools depend on MCP: + +- add/list MCP servers from the target Lean project directory, not from an unrelated folder; +- confirm `claude mcp list` shows the expected server in the same directory context; +- rerun the Numina command from the project root or the documented upstream runner cwd. + +If MCP works globally but fails in a project, treat it as a scope/cwd problem first. + +## Failure Routing + +- `401`, `AuthenticationError`, or invalid token: credentials or proxy auth. +- connection refused, timeout, DNS, or TLS error: proxy/network endpoint. +- `mcp` server missing, disconnected, or wrong cwd: MCP scope. +- `lake` or `lean` failure before Numina starts: target project is not buildable. +- `lean-toolchain` download failure in upstream examples: example project issue, not necessarily shared workspace failure. +- Numina produces Lean with `sorry`, `admit`, new `axiom`, or statement drift: reject output and validate/minimize locally. + +## Recovery Order + +1. Preserve the user's target file and theorem statement. +2. Verify local Lean workspace or target Lake project. +3. Verify Numina runtime and upstream checkout. +4. Verify Claude/API/proxy/MCP readiness only if Numina will be called. +5. Run the smallest approved Numina command. +6. Validate all changed Lean files locally before returning success. diff --git a/skills/lean-formalization/schemas/task.schema.json b/skills/lean-formalization/schemas/task.schema.json index 6af95e8..9facbb2 100644 --- a/skills/lean-formalization/schemas/task.schema.json +++ b/skills/lean-formalization/schemas/task.schema.json @@ -8,8 +8,8 @@ "type": "string", "enum": ["check", "configure", "prove_theorem", "formalize_statement", "repair_file", "complete_sorries", "batch", "review", "minimize_failure"] }, - "agent_mode": {"type": "string", "enum": ["numina-agent", "direct-validation-fallback"], "default": "numina-agent"}, - "backend": {"type": "string", "enum": ["official-numina", "none"], "default": "official-numina"}, + "agent_mode": {"type": "string", "enum": ["coding-agent", "numina-subagent", "hybrid"], "default": "coding-agent"}, + "backend": {"type": "string", "enum": ["none", "official-numina"], "default": "none"}, "cwd": {"type": "string"}, "file": {"type": "string"}, "folder": {"type": "string"}, diff --git a/skills/lean-formalization/scripts/ai4m_lean.py b/skills/lean-formalization/scripts/ai4m_lean.py index 67b91aa..e7cae6f 100644 --- a/skills/lean-formalization/scripts/ai4m_lean.py +++ b/skills/lean-formalization/scripts/ai4m_lean.py @@ -52,10 +52,10 @@ def add_common(parser: argparse.ArgumentParser) -> None: def build_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description="AI4Math Numina Lean Agent orchestration CLI") + parser = argparse.ArgumentParser(description="AI4Math coding-agent Lean skill CLI with optional Numina subagent orchestration") sub = parser.add_subparsers(dest="command", required=True) - env = sub.add_parser("env", help="Inspect Lean workspace and Numina Agent environment") + env = sub.add_parser("env", help="Inspect Lean workspace and optional Numina subagent environment") add_common(env) env.add_argument("--target", default=None) @@ -84,7 +84,7 @@ def build_parser() -> argparse.ArgumentParser: configure_parser.add_argument("--project-name", default=None, help="Lean project name for official Numina tutorial setup") for name in ("prove", "formalize", "repair", "complete-sorries"): - proof = sub.add_parser(name, help=f"Prepare a Numina Agent {name} task") + proof = sub.add_parser(name, help=f"Prepare a coding-agent {name} task") add_common(proof) proof.add_argument("--file", required=True) proof.add_argument("--target", default=None) @@ -95,7 +95,7 @@ def build_parser() -> argparse.ArgumentParser: if name == "formalize": proof.add_argument("--statement-file", default=None) - batch = sub.add_parser("batch", help="Prepare a Numina Agent folder task") + batch = sub.add_parser("batch", help="Prepare a coding-agent folder task") add_common(batch) batch.add_argument("--folder", required=True) batch.add_argument("--max-rounds", type=int, default=5) diff --git a/skills/lean-formalization/scripts/configure_lean.py b/skills/lean-formalization/scripts/configure_lean.py index 522d22b..1da0918 100644 --- a/skills/lean-formalization/scripts/configure_lean.py +++ b/skills/lean-formalization/scripts/configure_lean.py @@ -72,10 +72,10 @@ def inspect_environment(cwd: str | Path = ".", config_path: str | Path | None = "configuration_status": "configured" if not missing else "missing_config", "cwd": str(cwd_path), "agent": { - "mode": "numina-agent", - "backend": "official-numina", - "numina_required": True, - "numina_runtime": "default-official-runtime", + "mode": "coding-agent", + "backend": "none", + "numina_required": False, + "numina_runtime": "optional-subagent-backend", }, "lean": { "target": str(target_path), @@ -175,8 +175,8 @@ def configure( "allow_user_project_version_changes": False, }, "agent": { - "mode": "numina-agent", - "backend": "official-numina", + "mode": "coding-agent", + "backend": "none", }, }) diff --git a/skills/lean-formalization/scripts/direct_task.py b/skills/lean-formalization/scripts/direct_task.py index edd65f5..26dcc9e 100644 --- a/skills/lean-formalization/scripts/direct_task.py +++ b/skills/lean-formalization/scripts/direct_task.py @@ -49,10 +49,8 @@ def build_direct_task( missing.append("target") next_actions = [ - "Inspect Numina readiness and confirm the target project/file.", - "Explain the official Numina run command, prompt, max rounds, result directory, and credential state before approval.", - "Run the official Numina Lean Agent after approval.", - "Run check or lake env lean on Numina output.", + "Read the target Lean file and identify the exact declaration or error.", + "Run check or lake env lean after each small edit.", "Keep theorem statements unchanged unless the user explicitly approves a change.", "Stop when the file verifies without sorry/admit/axiom, or return minimize-failure output.", ] @@ -63,9 +61,9 @@ def build_direct_task( return { "ok": not missing, - "status": "numina_task_ready" if not missing else "missing_config", - "agent_mode": "numina-agent", - "backend": "official-numina", + "status": "coding_agent_task_ready" if not missing else "missing_config", + "agent_mode": "coding-agent", + "backend": "none", "task_type": task_type, "target": str(target_path), "cwd": str(cwd_path), @@ -81,8 +79,8 @@ def build_direct_task( "max_rounds": max_rounds, "missing_config": missing, "required_inputs": ["existing Lake project or shared reusable managed workspace"] if "lean_workspace" in missing else [], - "recommended_next_action": "run configure --create-workspace for the shared workspace or move target into a Lake project" if missing else "inspect Numina readiness, explain the official run, then call Numina after approval", - "numina_workflow": next_actions, + "recommended_next_action": "run configure --create-workspace for the shared workspace or move target into a Lake project" if missing else "coding agent should edit/check directly; use Numina only if the optional subagent path is approved", + "direct_workflow": next_actions, } diff --git a/skills/lean-formalization/scripts/smoke_test.py b/skills/lean-formalization/scripts/smoke_test.py index 83fcef3..be7720b 100644 --- a/skills/lean-formalization/scripts/smoke_test.py +++ b/skills/lean-formalization/scripts/smoke_test.py @@ -39,7 +39,7 @@ def run_smoke_test( "ai4math_numina_smoke_le_succ", ], "external_api_call": False, - "recommended_next_action": "run the bundled smoke target in the shared workspace before an official Numina call", + "recommended_next_action": "run the bundled smoke target, then start the coding-agent Lean task or discuss the optional Numina subagent path", } if not workspace_root: return { @@ -64,12 +64,12 @@ def run_smoke_test( "ai4math_numina_smoke_le_succ", ], "external_api_call": False, - "recommended_next_action": "use this built-in smoke target before a Numina run, then call official Numina after approval", + "recommended_next_action": "use this verified workspace for the next coding-agent Lean task; call official Numina only if the optional subagent path is approved", } lean_result = run_command(command, cwd=workspace_root, timeout=timeout) result["lean"] = lean_result result["ok"] = bool(lean_result.get("ok")) result["status"] = "ok" if result["ok"] else "lean_smoke_failed" if not result["ok"]: - result["recommended_next_action"] = "inspect the Lean smoke error, then repair the shared workspace before calling Numina" + result["recommended_next_action"] = "inspect the Lean smoke error, then repair the shared workspace before any Lean task or optional Numina call" return result diff --git a/skills/lean-formalization/scripts/tool_status.py b/skills/lean-formalization/scripts/tool_status.py index bb3383c..05051f6 100644 --- a/skills/lean-formalization/scripts/tool_status.py +++ b/skills/lean-formalization/scripts/tool_status.py @@ -76,4 +76,4 @@ def _recommend( return "install git before using Lake projects with remote dependencies" if missing_lean: return "install Lean/elan before creating the reusable Lean workspace" - return "ready for Numina Agent orchestration and local Lean validation" + return "ready for coding-agent Lean workflow and optional Numina subagent orchestration" diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py index 62d36d5..e296ae5 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -31,6 +31,7 @@ "references/interactive_orchestration.md", "references/direct_lean_workflow.md", "references/numina_runtime.md", + "references/numina_subagent_troubleshooting.md", "references/review_checklist.md", "references/failure_taxonomy.md", "references/numina_reverse_analysis.md", @@ -109,38 +110,39 @@ def _guidance_first_check() -> dict[str, Any]: required_phrases = [ "## Agent Playbook", "## Helper Toolbox", - "In this skill, Lean Agent means the official Numina Lean Agent runtime.", - "Default execution mode is Numina Agent mode.", - "The coding agent orchestrates Numina deployment, configuration, invocation, and local Lean validation.", - "Direct Lean editing is a validation and fallback path, not the default Lean Agent mode.", + "This is a coding-agent-first Lean skill.", + "The coding agent is the primary Lean worker.", + "Official Numina is an optional deployable subagent backend.", + "Default execution mode is coding-agent mode.", + "Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run.", "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", "If the user's language is ambiguous, default to Chinese.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", - "Opening readiness should inspect Numina readiness before recommending work.", - "Do not say API keys are unnecessary until the Numina mode is clear.", + "Opening readiness should inspect local Lean readiness and Numina subagent readiness separately.", + "Do not require API keys for the default coding-agent path.", "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "offer a small next-step menu", "Ask at most one blocking question at a time.", "The bundled CLI is a helper toolbox, not the workflow driver.", - "Use official Numina through a human-in-the-loop runtime workflow.", + "Use official Numina through a human-in-the-loop subagent workflow.", "Do not turn helper commands into a closed proof workflow.", - "Do not redefine Lean Agent as the coding agent.", + "Do not remove the official Numina subagent path.", ] missing = [phrase for phrase in required_phrases if phrase not in text] orchestration_required = [ "## Session Opening", - "In this skill, Lean Agent means the official Numina Lean Agent runtime.", - "Default execution mode is Numina Agent mode.", + "This is a coding-agent-first Lean skill.", + "Official Numina is an optional deployable subagent backend.", "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", - "Opening readiness should inspect Numina readiness before recommending work.", - "Do not say API keys are unnecessary until the Numina mode is clear.", + "Opening readiness should inspect local Lean readiness and Numina subagent readiness separately.", + "Do not require API keys for the default coding-agent path.", "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "A good opening ends with one decision question, not a checklist.", ] @@ -149,8 +151,8 @@ def _guidance_first_check() -> dict[str, Any]: openai_required = [ "请用中文开始", "如果用户明确使用其他语言", - "Lean Agent 默认指 Numina", - "先检查 Numina readiness", + "默认走 coding agent Lean 工作流", + "Numina 是可部署的可选 subagent", ] openai_missing = [phrase for phrase in openai_required if phrase not in openai_yaml] return { diff --git a/skills/lean-formalization/tests/test_cli.py b/skills/lean-formalization/tests/test_cli.py index 0da0223..c2ea4d8 100644 --- a/skills/lean-formalization/tests/test_cli.py +++ b/skills/lean-formalization/tests/test_cli.py @@ -18,7 +18,7 @@ class CliTests(unittest.TestCase): - def test_dry_run_prove_outputs_numina_task(self) -> None: + def test_dry_run_prove_outputs_coding_agent_task(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) workspace = root / ".ai4math" / "lean-workspace" @@ -47,9 +47,9 @@ def test_dry_run_prove_outputs_numina_task(self) -> None: self.assertEqual(result.returncode, 0, result.stderr) payload = json.loads(result.stdout) self.assertEqual(payload["status"], "dry_run") - self.assertEqual(payload["agent_mode"], "numina-agent") - self.assertEqual(payload["backend"], "official-numina") - self.assertIn("numina_workflow", payload) + self.assertEqual(payload["agent_mode"], "coding-agent") + self.assertEqual(payload["backend"], "none") + self.assertIn("direct_workflow", payload) self.assertNotIn("command", payload) def test_check_skip_build_outputs_json(self) -> None: diff --git a/skills/lean-formalization/tests/test_common_config.py b/skills/lean-formalization/tests/test_common_config.py index b6aff36..67411ef 100644 --- a/skills/lean-formalization/tests/test_common_config.py +++ b/skills/lean-formalization/tests/test_common_config.py @@ -17,14 +17,14 @@ def test_load_toml_has_python39_fallback(self) -> None: with tempfile.TemporaryDirectory() as tmp: path = Path(tmp) / "config.toml" path.write_text( - '[agent]\nmode = "numina-agent"\nbackend = "official-numina"\n' + '[agent]\nmode = "coding-agent"\nbackend = "none"\n' '[lean]\nreuse_managed_workspace = true\n', encoding="utf-8", ) with patch("common.tomllib", None): data = load_toml(path) - self.assertEqual(data["agent"]["backend"], "official-numina") + self.assertEqual(data["agent"]["backend"], "none") self.assertTrue(data["lean"]["reuse_managed_workspace"]) def test_expand_path_preserves_symlink_text(self) -> None: diff --git a/skills/lean-formalization/tests/test_configure_lean.py b/skills/lean-formalization/tests/test_configure_lean.py index 9de11b9..9ece591 100644 --- a/skills/lean-formalization/tests/test_configure_lean.py +++ b/skills/lean-formalization/tests/test_configure_lean.py @@ -15,7 +15,7 @@ class ConfigureLeanTests(unittest.TestCase): - def test_existing_lean_project_is_numina_agent_ready(self) -> None: + def test_existing_lean_project_is_coding_agent_ready(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) target = root / "Main.lean" @@ -28,9 +28,10 @@ def test_existing_lean_project_is_numina_agent_ready(self) -> None: result = inspect_environment(root, target=target) self.assertTrue(result["ok"]) - self.assertEqual(result["agent"]["mode"], "numina-agent") - self.assertEqual(result["agent"]["backend"], "official-numina") - self.assertTrue(result["agent"]["numina_required"]) + self.assertEqual(result["agent"]["mode"], "coding-agent") + self.assertEqual(result["agent"]["backend"], "none") + self.assertFalse(result["agent"]["numina_required"]) + self.assertEqual(result["agent"]["numina_runtime"], "optional-subagent-backend") self.assertEqual(result["missing_config"], []) self.assertIn("numina", result) self.assertIn("readiness", result["numina"]) @@ -46,8 +47,8 @@ def test_save_local_writes_lean_agent_config(self) -> None: self.assertFalse(result["ok"]) self.assertEqual(result["status"], "missing_config") - self.assertEqual(local["agent"]["backend"], "official-numina") - self.assertEqual(local["agent"]["mode"], "numina-agent") + self.assertEqual(local["agent"]["backend"], "none") + self.assertEqual(local["agent"]["mode"], "coding-agent") self.assertEqual(local["lean"]["preferred_toolchain"], "leanprover/lean4:v4.28.0") self.assertIn("lean_agent.local.toml", (root / ".ai4math" / ".gitignore").read_text()) diff --git a/skills/lean-formalization/tests/test_direct_task.py b/skills/lean-formalization/tests/test_direct_task.py index b462db8..9f5815c 100644 --- a/skills/lean-formalization/tests/test_direct_task.py +++ b/skills/lean-formalization/tests/test_direct_task.py @@ -14,7 +14,7 @@ class DirectTaskTests(unittest.TestCase): - def test_managed_workspace_routes_standalone_file_to_numina_agent(self) -> None: + def test_managed_workspace_routes_standalone_file_to_coding_agent(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) workspace = root / ".ai4math" / "lean-workspace" @@ -28,9 +28,9 @@ def test_managed_workspace_routes_standalone_file_to_numina_agent(self) -> None: result = build_direct_task("prove", root, target) self.assertTrue(result["ok"]) - self.assertEqual(result["status"], "numina_task_ready") - self.assertEqual(result["agent_mode"], "numina-agent") - self.assertEqual(result["backend"], "official-numina") + self.assertEqual(result["status"], "coding_agent_task_ready") + self.assertEqual(result["agent_mode"], "coding-agent") + self.assertEqual(result["backend"], "none") self.assertEqual(result["workspace_mode"], "managed_workspace") self.assertEqual(result["missing_config"], []) @@ -46,7 +46,7 @@ def test_missing_workspace_reports_required_input(self) -> None: self.assertFalse(result["ok"]) self.assertEqual(result["status"], "missing_config") self.assertIn("lean_workspace", result["missing_config"]) - self.assertEqual(result["backend"], "official-numina") + self.assertEqual(result["backend"], "none") def test_dry_run_marks_ready_task_without_external_command(self) -> None: with tempfile.TemporaryDirectory() as tmp: @@ -60,7 +60,8 @@ def test_dry_run_marks_ready_task_without_external_command(self) -> None: self.assertTrue(result["ok"]) self.assertEqual(result["status"], "dry_run") - self.assertEqual(result["backend"], "official-numina") + self.assertEqual(result["backend"], "none") + self.assertIn("direct_workflow", result) self.assertNotIn("command", result) From e426475386d43102af13606f6a1e02c7b71a87c1 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 12:58:57 +0800 Subject: [PATCH 27/37] Distill Lean specialist agent patterns --- README.md | 3 +- README.zh-CN.md | 3 +- skills/lean-formalization/SKILL.md | 5 +- skills/lean-formalization/agents/openai.yaml | 4 +- .../references/direct_lean_workflow.md | 16 ++--- .../references/interactive_orchestration.md | 6 +- .../references/numina_reverse_analysis.md | 6 +- .../references/specialist_agent_patterns.md | 63 +++++++++++++++++++ .../scripts/verify_delivery.py | 5 ++ 9 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 skills/lean-formalization/references/specialist_agent_patterns.md diff --git a/README.md b/README.md index fb11cb1..217328b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Chinese guide: [README.zh-CN.md](README.zh-CN.md) -`lean-formalization` helps a coding agent work with Lean 4 formalization, proof repair, and validation tasks. +`lean-formalization` helps a coding agent work with Lean 4 formalization, proof repair, and validation tasks. It is coding-agent-first, but it distills useful patterns from Lean-specialist agents such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. ## When To Use It @@ -55,6 +55,7 @@ Constraints: - Theorem formalization, proof repair, proof completion, and `sorry` completion. - Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. - Minimal failing Lean fragment extraction when a proof is blocked. +- Distilled Lean-specialist agent patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. - Optional official `project-numina/numina-lean-agent` deployment/call flow, mediated by the coding agent. Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `~/.ai4math/numina-runtime/` by default. diff --git a/README.zh-CN.md b/README.zh-CN.md index f10ec87..19421f1 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,7 +2,7 @@ [English](README.md) | 简体中文 -`lean-formalization` 帮助 coding agent 处理 Lean 4 形式化、proof repair 和 validation 任务。 +`lean-formalization` 帮助 coding agent 处理 Lean 4 形式化、proof repair 和 validation 任务。它是 coding-agent-first,但会蒸馏 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 的有效机制。 ## 适合什么任务 @@ -66,6 +66,7 @@ claim 前都应先问用户。 - patch review:检查 `sorry`、`admit`、新引入的 `axiom` 和 theorem statement drift。 - 可选 official `project-numina/numina-lean-agent` runtime 设置和调用。 - proof blocked 时抽取最小失败 Lean fragment。 +- 蒸馏 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 ## 维护者检查 diff --git a/skills/lean-formalization/SKILL.md b/skills/lean-formalization/SKILL.md index 29afaab..e4aaefa 100644 --- a/skills/lean-formalization/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -9,6 +9,8 @@ Use this skill when the user wants a coding agent to do Lean 4 formalization, pr This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker. It reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, preserves theorem statements, and iterates with the user. Default execution mode is coding-agent mode. +Distill Lean-specialist agent patterns into the default coding-agent workflow. Learn from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents by abstracting their mechanisms: project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Use specialist-agent patterns as mechanisms, not mandatory external services. + Official Numina is an optional deployable subagent backend. Keep the official Numina deployment/call path available for users who ask for the official Lean Agent, batch proof search, or an external subagent run. Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run. Match the user's language by default. If the user's language is ambiguous, default to Chinese. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. A language switch is not a task reset. Keep the current environment state, prior diagnosis, and recommended next action, then continue leading in the new language. @@ -36,7 +38,7 @@ Do not remove the official Numina subagent path. Treat it as an optional backend 7. When reporting readiness, lead with local Lean readiness, then Numina subagent readiness. If Numina credentials are missing, say that only the optional Numina subagent path needs configuration. 8. Before a Numina setup or run, inspect `doctor` readiness, explain the deployment/call, target project, prompt, result directory, credential/proxy/MCP state, and local validation plan; proceed only after approval. 9. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -10. Edit Lean directly in small steps for the default coding-agent path. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. +10. Edit Lean directly in small steps for the default coding-agent path, using distilled specialist-agent patterns such as theorem-state inspection, nearby lemma retrieval, bounded proof attempts, failed-strategy notes, and minimal failure extraction. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. 11. Preserve theorem statements unless the user explicitly approves a change. 12. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. 13. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. @@ -76,6 +78,7 @@ When using the official Numina runtime, follow `references/numina_runtime.md`. F ## References - Read `references/direct_lean_workflow.md` for the default coding-agent proof/repair/formalization loop. +- Read `references/specialist_agent_patterns.md` when adapting ideas from Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP, or other Lean-specialist agents. - Read `references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. - Read `references/numina_runtime.md` when the user wants the official Numina deployment/call path. - Read `references/numina_subagent_troubleshooting.md` when Numina auth, proxy, MCP, or runner failures appear. diff --git a/skills/lean-formalization/agents/openai.yaml b/skills/lean-formalization/agents/openai.yaml index dc0c37f..e2fae86 100644 --- a/skills/lean-formalization/agents/openai.yaml +++ b/skills/lean-formalization/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: Lean Formalization -short_description: Interactive Lean 4 verification for coding agents with reusable mathlib workspaces and optional official Numina subagent calls. -default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 +short_description: Interactive Lean 4 verification for coding agents that distill Lean-specialist agent patterns, with optional official Numina subagent calls. +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。这个 skill 会蒸馏 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 等 Lean 专用 agent 的机制:项目门禁、statement normalization、theorem-state loop、premise retrieval、bounded search、失败记忆、Lean/Lake oracle 和 minimal failure handoff。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 diff --git a/skills/lean-formalization/references/direct_lean_workflow.md b/skills/lean-formalization/references/direct_lean_workflow.md index 15a14d7..1149a19 100644 --- a/skills/lean-formalization/references/direct_lean_workflow.md +++ b/skills/lean-formalization/references/direct_lean_workflow.md @@ -1,6 +1,6 @@ # Direct Coding-Agent Lean Workflow -This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. +This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. It distills Lean-specialist agent patterns into local work: theorem-state loops, premise retrieval, bounded proof attempts, failed-strategy memory, and minimal failure handoff. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. ## Guidance-First Loop @@ -8,12 +8,14 @@ This is the default workflow. The coding agent reads and edits Lean directly, ru 2. Inspect the target files, imports, nearby lemmas, and current Lean errors. 3. Choose the validation context: existing Lake project first, managed workspace only for standalone files. 4. For formalization, draft the Lean declaration and ask for confirmation before long proof work. -5. Make one small Lean edit at a time. -6. Run Lean/Lake validation after meaningful edits, usually `lake env lean `, `lake build`, or the helper `check` command. -7. Diagnose the first concrete Lean error or unsolved goal before changing strategy. -8. Add helper lemmas only when they reduce proof complexity and keep theorem statements unchanged. -9. Review the final patch with direct inspection and, when useful, `review` or `detect-sorry`. -10. If blocked, use direct reduction and/or `minimize-failure` to return the smallest failing Lean fragment plus exact errors/goals. +5. Build a compact local context pack from current goals, nearby proofs, relevant declarations, and failed attempts. +6. Make one small Lean edit at a time. +7. Run Lean/Lake validation after meaningful edits, usually `lake env lean `, `lake build`, or the helper `check` command. +8. Diagnose the first concrete Lean error or unsolved goal before changing strategy. +9. Search before inventing: use existing imports, nearby lemmas, and project/mathlib declarations before adding helper lemmas. +10. Add helper lemmas only when they reduce proof complexity and keep theorem statements unchanged. +11. Review the final patch with direct inspection and, when useful, `review` or `detect-sorry`. +12. If blocked, use direct reduction and/or `minimize-failure` to return the smallest failing Lean fragment plus exact errors/goals and tried routes. ## When to Use Helpers diff --git a/skills/lean-formalization/references/interactive_orchestration.md b/skills/lean-formalization/references/interactive_orchestration.md index 6cadee5..448eb07 100644 --- a/skills/lean-formalization/references/interactive_orchestration.md +++ b/skills/lean-formalization/references/interactive_orchestration.md @@ -1,8 +1,8 @@ # Interactive Orchestration -The coordinating coding agent owns user interaction, Lean proof/formalization work, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. +The coordinating coding agent owns user interaction, Lean proof/formalization work, distilled Lean-specialist agent patterns, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. -This reference covers the guidance layer: session opening, intake, task classification, direct coding-agent Lean work, optional Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. +This reference covers the guidance layer: session opening, intake, task classification, direct coding-agent Lean work, specialist-agent pattern selection, optional Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. ## Session Opening @@ -10,6 +10,8 @@ If the user's language is ambiguous, default to Chinese. The skill display name, This is a coding-agent-first Lean skill. Official Numina is an optional deployable subagent backend. +The default coding-agent path should still absorb Lean-specialist agent mechanisms: project gating, statement normalization, theorem-state loops, premise retrieval, bounded proof search, failed-strategy memory, Lean/Lake validation, and minimized failure handoff. + Lead the interaction; do not wait for the user to drive every step. On a broad request, first orient to the current state instead of asking for every input at once: - inspect whether the current directory is a Lake project; diff --git a/skills/lean-formalization/references/numina_reverse_analysis.md b/skills/lean-formalization/references/numina_reverse_analysis.md index c7c0e3f..2a4dcb4 100644 --- a/skills/lean-formalization/references/numina_reverse_analysis.md +++ b/skills/lean-formalization/references/numina_reverse_analysis.md @@ -1,6 +1,6 @@ -# Numina Reverse Analysis for AI4Math +# Numina and Lean-Specialist Agent Distillation -This reference records what this coding-agent Lean skill learns from the public Numina Lean Agent workflow, and which parts remain available through the optional official Numina subagent backend. For deployment/call instructions, use `numina_runtime.md`. +This reference records what this coding-agent Lean skill learns from the public Numina Lean Agent workflow, and how those lessons fit the broader Lean-specialist agent pattern library in `specialist_agent_patterns.md`. For deployment/call instructions, use `numina_runtime.md`. ## Source Scope @@ -8,7 +8,7 @@ This reference records what this coding-agent Lean skill learns from the public - Result repository: https://github.com/project-numina/Numina-Putnam2025 - Paper reference: https://arxiv.org/abs/2601.14027 -The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to make coding agents better Lean workers while preserving a deployable path to the official Numina runtime when the user wants a subagent. +The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to distill reusable Lean-agent mechanisms into a comprehensive coding-agent skill while preserving a deployable path to the official Numina runtime when the user wants a subagent. ## Distilled Patterns diff --git a/skills/lean-formalization/references/specialist_agent_patterns.md b/skills/lean-formalization/references/specialist_agent_patterns.md new file mode 100644 index 0000000..4e9dde7 --- /dev/null +++ b/skills/lean-formalization/references/specialist_agent_patterns.md @@ -0,0 +1,63 @@ +# Lean-Specialist Agent Pattern Distillation + +This reference explains how the coding-agent-first skill absorbs Lean-specialist agent designs without making any external agent mandatory. Preserve the mechanism, not prompts, benchmark-specific assumptions, or private implementation details. + +## Source Families + +- Numina-style coding-agent orchestration: project setup, official runner calls, Claude/MCP/tool integration, bounded external proof attempts, and local Lean validation. +- LeanDojo/ReProver-style loops: theorem state as the central object, premise retrieval, tactic generation, execution feedback, and proof search evaluation. +- LeanCopilot-style assistance: programmatic tactic, premise, and proof-search hooks that a human/coding agent can treat as optional suggestions. +- COPRA-style proof search: stateful attempts, backtracking, failed-strategy memory, and compact proof-state reporting. +- Lean LSP/MCP-style integration: editor/server feedback, goal inspection, diagnostics, and tool scope tied to the target project. +- Lightweight iterative agents: small edit/check loops, local context retrieval, and explicit stop conditions. + +These sources are patterns to distill. Do not claim parity with a specialist prover unless the original backend is actually called and validated. + +Public source anchors: + +- Numina Lean Agent: `https://github.com/project-numina/numina-lean-agent` +- LeanDojo/ReProver: `https://github.com/lean-dojo/LeanDojo` +- LeanCopilot: `https://github.com/lean-dojo/LeanCopilot` +- COPRA: `https://github.com/trishullab/copra` + +## Distilled Default Workflow + +1. Gate the project: identify the Lake root, toolchain, mathlib revision, imports, and build status before proof work. +2. Normalize the target: locate the authoritative theorem statement, declaration name, hypotheses, namespace, and allowed statement changes. +3. Build a local context pack: nearby lemmas, imported modules, relevant declarations from `rg`, current goals, and prior failed attempts. +4. Run the theorem-state loop: make one small edit, run Lean, read the first concrete error or goal, update the context pack, and continue. +5. Use bounded search: try a small number of plausible tactic/proof routes; record failed routes so the agent does not cycle. +6. Retrieve before inventing: search existing project/mathlib names and nearby proofs before adding helper lemmas. +7. Validate as oracle: Lean/Lake success is required; final patches must not contain `sorry`, `admit`, new `axiom`, or unapproved statement drift. +8. Escalate deliberately: call optional Numina or another specialist backend only after explaining target, credentials/proxy/MCP state, result directory, and validation plan. +9. Hand off minimally: when blocked, return the smallest failing Lean fragment, exact goals/errors, tried routes, and the next mathematical decision. + +## Pattern Map + +| Specialist mechanism | Coding-agent integration | +| --- | --- | +| Runtime/environment gate | `env`, `doctor`, `configure`, direct Lake root inspection | +| Theorem-state centered search | Lean error/goal loop after each small edit | +| Premise retrieval | `rg`, nearby imports/proofs, project declarations, optional external search | +| Bounded proof attempts | `max_rounds`, local iteration caps, failed-strategy notes | +| Backtracking/failure memory | Record tried tactic families and rejected statement changes | +| External proof backend | Optional official Numina subagent, never required for default work | +| Validation oracle | Lean/Lake plus `review` and `detect-sorry` | +| Failure artifact | `minimize-failure` and exact errors/goals | + +## Escalation Rule + +Default to distilled local patterns. Escalate to a real specialist backend only when: + +- the user asks for Numina, official Lean Agent, batch proof search, or an external subagent; +- local bounded attempts are cycling and the user approves a backend call; +- the required credentials, proxy, MCP scope, and target project are understood; +- all backend output will still be reviewed and checked locally. + +## Anti-Patterns + +- Do not replace proof work with a CLI workflow that only asks the user for more input. +- Do not treat a missing Numina key as blocking ordinary coding-agent Lean work. +- Do not copy upstream prompts or claim hidden benchmark behavior. +- Do not add helper lemmas or theorem statement changes just to make a proof easier unless the user approves. +- Do not let an external backend output bypass local Lean validation and patch review. diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py index e296ae5..1d79a28 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -30,6 +30,7 @@ "references/lean_runtime_configuration.md", "references/interactive_orchestration.md", "references/direct_lean_workflow.md", + "references/specialist_agent_patterns.md", "references/numina_runtime.md", "references/numina_subagent_troubleshooting.md", "references/review_checklist.md", @@ -114,6 +115,8 @@ def _guidance_first_check() -> dict[str, Any]: "The coding agent is the primary Lean worker.", "Official Numina is an optional deployable subagent backend.", "Default execution mode is coding-agent mode.", + "Distill Lean-specialist agent patterns into the default coding-agent workflow.", + "Use specialist-agent patterns as mechanisms, not mandatory external services.", "Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run.", "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", @@ -136,6 +139,7 @@ def _guidance_first_check() -> dict[str, Any]: "## Session Opening", "This is a coding-agent-first Lean skill.", "Official Numina is an optional deployable subagent backend.", + "The default coding-agent path should still absorb Lean-specialist agent mechanisms:", "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", "A language switch is not a task reset.", @@ -152,6 +156,7 @@ def _guidance_first_check() -> dict[str, Any]: "请用中文开始", "如果用户明确使用其他语言", "默认走 coding agent Lean 工作流", + "这个 skill 会蒸馏", "Numina 是可部署的可选 subagent", ] openai_missing = [phrase for phrase in openai_required if phrase not in openai_yaml] From 8a51a497e6b1fb73158e369b016d1a1ab1650445 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 13:15:10 +0800 Subject: [PATCH 28/37] Use learning terminology for specialist agent patterns --- README.md | 4 ++-- README.zh-CN.md | 4 ++-- skills/lean-formalization/SKILL.md | 6 +++--- skills/lean-formalization/agents/openai.yaml | 4 ++-- .../references/direct_lean_workflow.md | 2 +- .../references/interactive_orchestration.md | 2 +- .../references/numina_reverse_analysis.md | 6 +++--- .../references/specialist_agent_patterns.md | 10 +++++----- skills/lean-formalization/scripts/verify_delivery.py | 4 ++-- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 217328b..a0a05b4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Chinese guide: [README.zh-CN.md](README.zh-CN.md) -`lean-formalization` helps a coding agent work with Lean 4 formalization, proof repair, and validation tasks. It is coding-agent-first, but it distills useful patterns from Lean-specialist agents such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. +`lean-formalization` helps a coding agent work with Lean 4 formalization, proof repair, and validation tasks. It is coding-agent-first, but it learns from and integrates useful patterns from Lean-specialist agents such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. ## When To Use It @@ -55,7 +55,7 @@ Constraints: - Theorem formalization, proof repair, proof completion, and `sorry` completion. - Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. - Minimal failing Lean fragment extraction when a proof is blocked. -- Distilled Lean-specialist agent patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. +- Learned Lean-specialist agent patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. - Optional official `project-numina/numina-lean-agent` deployment/call flow, mediated by the coding agent. Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `~/.ai4math/numina-runtime/` by default. diff --git a/README.zh-CN.md b/README.zh-CN.md index 19421f1..7f210f0 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,7 +2,7 @@ [English](README.md) | 简体中文 -`lean-formalization` 帮助 coding agent 处理 Lean 4 形式化、proof repair 和 validation 任务。它是 coding-agent-first,但会蒸馏 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 的有效机制。 +`lean-formalization` 帮助 coding agent 处理 Lean 4 形式化、proof repair 和 validation 任务。它是 coding-agent-first,但会学习并整合 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 的有效机制。 ## 适合什么任务 @@ -66,7 +66,7 @@ claim 前都应先问用户。 - patch review:检查 `sorry`、`admit`、新引入的 `axiom` 和 theorem statement drift。 - 可选 official `project-numina/numina-lean-agent` runtime 设置和调用。 - proof blocked 时抽取最小失败 Lean fragment。 -- 蒸馏 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 +- 学习并整合 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 ## 维护者检查 diff --git a/skills/lean-formalization/SKILL.md b/skills/lean-formalization/SKILL.md index e4aaefa..36dcf96 100644 --- a/skills/lean-formalization/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -9,7 +9,7 @@ Use this skill when the user wants a coding agent to do Lean 4 formalization, pr This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker. It reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, preserves theorem statements, and iterates with the user. Default execution mode is coding-agent mode. -Distill Lean-specialist agent patterns into the default coding-agent workflow. Learn from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents by abstracting their mechanisms: project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Use specialist-agent patterns as mechanisms, not mandatory external services. +Learn from Lean-specialist agent patterns and integrate them into the default coding-agent workflow. Learn from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents by abstracting their mechanisms: project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Use specialist-agent patterns as mechanisms, not mandatory external services. Official Numina is an optional deployable subagent backend. Keep the official Numina deployment/call path available for users who ask for the official Lean Agent, batch proof search, or an external subagent run. Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run. @@ -38,7 +38,7 @@ Do not remove the official Numina subagent path. Treat it as an optional backend 7. When reporting readiness, lead with local Lean readiness, then Numina subagent readiness. If Numina credentials are missing, say that only the optional Numina subagent path needs configuration. 8. Before a Numina setup or run, inspect `doctor` readiness, explain the deployment/call, target project, prompt, result directory, credential/proxy/MCP state, and local validation plan; proceed only after approval. 9. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -10. Edit Lean directly in small steps for the default coding-agent path, using distilled specialist-agent patterns such as theorem-state inspection, nearby lemma retrieval, bounded proof attempts, failed-strategy notes, and minimal failure extraction. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. +10. Edit Lean directly in small steps for the default coding-agent path, using learned specialist-agent patterns such as theorem-state inspection, nearby lemma retrieval, bounded proof attempts, failed-strategy notes, and minimal failure extraction. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. 11. Preserve theorem statements unless the user explicitly approves a change. 12. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. 13. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. @@ -85,4 +85,4 @@ When using the official Numina runtime, follow `references/numina_runtime.md`. F - Read `references/interactive_orchestration.md` when guiding user intake and task decomposition. - Read `references/review_checklist.md` before accepting a Lean patch. - Read `references/failure_taxonomy.md` when reporting a blocked proof. -- Read `references/numina_reverse_analysis.md` when explaining which Numina mechanisms were distilled and which are delegated to the optional official runtime. +- Read `references/numina_reverse_analysis.md` when explaining which Numina mechanisms were learned and which are delegated to the optional official runtime. diff --git a/skills/lean-formalization/agents/openai.yaml b/skills/lean-formalization/agents/openai.yaml index e2fae86..4c43317 100644 --- a/skills/lean-formalization/agents/openai.yaml +++ b/skills/lean-formalization/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: Lean Formalization -short_description: Interactive Lean 4 verification for coding agents that distill Lean-specialist agent patterns, with optional official Numina subagent calls. -default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。这个 skill 会蒸馏 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 等 Lean 专用 agent 的机制:项目门禁、statement normalization、theorem-state loop、premise retrieval、bounded search、失败记忆、Lean/Lake oracle 和 minimal failure handoff。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 +short_description: Interactive Lean 4 verification for coding agents that learn from Lean-specialist agent patterns, with optional official Numina subagent calls. +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。这个 skill 会学习并整合 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 等 Lean 专用 agent 的机制:项目门禁、statement normalization、theorem-state loop、premise retrieval、bounded search、失败记忆、Lean/Lake oracle 和 minimal failure handoff。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 diff --git a/skills/lean-formalization/references/direct_lean_workflow.md b/skills/lean-formalization/references/direct_lean_workflow.md index 1149a19..d5ef9a9 100644 --- a/skills/lean-formalization/references/direct_lean_workflow.md +++ b/skills/lean-formalization/references/direct_lean_workflow.md @@ -1,6 +1,6 @@ # Direct Coding-Agent Lean Workflow -This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. It distills Lean-specialist agent patterns into local work: theorem-state loops, premise retrieval, bounded proof attempts, failed-strategy memory, and minimal failure handoff. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. +This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. It learns from Lean-specialist agent patterns and integrates them into local work: theorem-state loops, premise retrieval, bounded proof attempts, failed-strategy memory, and minimal failure handoff. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. ## Guidance-First Loop diff --git a/skills/lean-formalization/references/interactive_orchestration.md b/skills/lean-formalization/references/interactive_orchestration.md index 448eb07..8ac99da 100644 --- a/skills/lean-formalization/references/interactive_orchestration.md +++ b/skills/lean-formalization/references/interactive_orchestration.md @@ -1,6 +1,6 @@ # Interactive Orchestration -The coordinating coding agent owns user interaction, Lean proof/formalization work, distilled Lean-specialist agent patterns, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. +The coordinating coding agent owns user interaction, Lean proof/formalization work, learned Lean-specialist agent patterns, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. This reference covers the guidance layer: session opening, intake, task classification, direct coding-agent Lean work, specialist-agent pattern selection, optional Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. diff --git a/skills/lean-formalization/references/numina_reverse_analysis.md b/skills/lean-formalization/references/numina_reverse_analysis.md index 2a4dcb4..d61ace4 100644 --- a/skills/lean-formalization/references/numina_reverse_analysis.md +++ b/skills/lean-formalization/references/numina_reverse_analysis.md @@ -1,4 +1,4 @@ -# Numina and Lean-Specialist Agent Distillation +# Numina and Lean-Specialist Agent Learning This reference records what this coding-agent Lean skill learns from the public Numina Lean Agent workflow, and how those lessons fit the broader Lean-specialist agent pattern library in `specialist_agent_patterns.md`. For deployment/call instructions, use `numina_runtime.md`. @@ -8,9 +8,9 @@ This reference records what this coding-agent Lean skill learns from the public - Result repository: https://github.com/project-numina/Numina-Putnam2025 - Paper reference: https://arxiv.org/abs/2601.14027 -The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to distill reusable Lean-agent mechanisms into a comprehensive coding-agent skill while preserving a deployable path to the official Numina runtime when the user wants a subagent. +The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to learn reusable Lean-agent mechanisms and integrate them into a comprehensive coding-agent skill while preserving a deployable path to the official Numina runtime when the user wants a subagent. -## Distilled Patterns +## Learned Patterns 1. Use a coding agent as the primary Lean worker, with Numina available as an optional subagent. 2. Keep Lean/Lake validation as the correctness oracle. diff --git a/skills/lean-formalization/references/specialist_agent_patterns.md b/skills/lean-formalization/references/specialist_agent_patterns.md index 4e9dde7..9621b3f 100644 --- a/skills/lean-formalization/references/specialist_agent_patterns.md +++ b/skills/lean-formalization/references/specialist_agent_patterns.md @@ -1,6 +1,6 @@ -# Lean-Specialist Agent Pattern Distillation +# Lean-Specialist Agent Pattern Learning -This reference explains how the coding-agent-first skill absorbs Lean-specialist agent designs without making any external agent mandatory. Preserve the mechanism, not prompts, benchmark-specific assumptions, or private implementation details. +This reference explains how the coding-agent-first skill learns from Lean-specialist agent designs without making any external agent mandatory. Preserve the mechanism, not prompts, benchmark-specific assumptions, or private implementation details. ## Source Families @@ -11,7 +11,7 @@ This reference explains how the coding-agent-first skill absorbs Lean-specialist - Lean LSP/MCP-style integration: editor/server feedback, goal inspection, diagnostics, and tool scope tied to the target project. - Lightweight iterative agents: small edit/check loops, local context retrieval, and explicit stop conditions. -These sources are patterns to distill. Do not claim parity with a specialist prover unless the original backend is actually called and validated. +These sources are patterns to learn from and integrate. Do not claim parity with a specialist prover unless the original backend is actually called and validated. Public source anchors: @@ -20,7 +20,7 @@ Public source anchors: - LeanCopilot: `https://github.com/lean-dojo/LeanCopilot` - COPRA: `https://github.com/trishullab/copra` -## Distilled Default Workflow +## Learned Default Workflow 1. Gate the project: identify the Lake root, toolchain, mathlib revision, imports, and build status before proof work. 2. Normalize the target: locate the authoritative theorem statement, declaration name, hypotheses, namespace, and allowed statement changes. @@ -47,7 +47,7 @@ Public source anchors: ## Escalation Rule -Default to distilled local patterns. Escalate to a real specialist backend only when: +Default to learned local patterns. Escalate to a real specialist backend only when: - the user asks for Numina, official Lean Agent, batch proof search, or an external subagent; - local bounded attempts are cycling and the user approves a backend call; diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py index 1d79a28..528d0e2 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -115,7 +115,7 @@ def _guidance_first_check() -> dict[str, Any]: "The coding agent is the primary Lean worker.", "Official Numina is an optional deployable subagent backend.", "Default execution mode is coding-agent mode.", - "Distill Lean-specialist agent patterns into the default coding-agent workflow.", + "Learn from Lean-specialist agent patterns and integrate them into the default coding-agent workflow.", "Use specialist-agent patterns as mechanisms, not mandatory external services.", "Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run.", "Use the bundled smoke test when no user target is available.", @@ -156,7 +156,7 @@ def _guidance_first_check() -> dict[str, Any]: "请用中文开始", "如果用户明确使用其他语言", "默认走 coding agent Lean 工作流", - "这个 skill 会蒸馏", + "这个 skill 会学习并整合", "Numina 是可部署的可选 subagent", ] openai_missing = [phrase for phrase in openai_required if phrase not in openai_yaml] From 60c665190cca6f83421eda08f06e798c87cb14e0 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 13:40:26 +0800 Subject: [PATCH 29/37] docs: align lean skill docs for main --- README.md | 2 +- README.zh-CN.md | 2 +- skills/lean-formalization/README.md | 30 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 skills/lean-formalization/README.md diff --git a/README.md b/README.md index a0a05b4..916add9 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The agent should produce Lean patches, validation summaries, blocked-goal explan Copy this to your coding agent: ```text -Please install the `lean-formalization` skill from https://github.com/VeryMath/AI4Math-Lean-Agents.git (branch: feature/numina-runtime-delivery). Read `.agent.md`, install the declared Skill entrypoint, verify that `$lean-formalization` is discoverable, and tell me whether I need to restart the agent. +Please install the `lean-formalization` skill from https://github.com/VeryMath/AI4Math-Lean-Agents.git. Read `.agent.md`, install the declared Skill entrypoint, verify that `$lean-formalization` is discoverable, and tell me whether I need to restart the agent. ``` If you already have this skill repository locally, replace the repository URL diff --git a/README.zh-CN.md b/README.zh-CN.md index 7f210f0..8a04a9c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -22,7 +22,7 @@ Agent 应产出 Lean patches、validation summaries、blocked-goal explanations 把下面这句话发给你的 coding agent: ```text -请帮我安装 `lean-formalization` skill,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git,分支:feature/numina-runtime-delivery。请读取 `.agent.md`,安装其中声明的 Skill entrypoint,验证 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 +请帮我安装 `lean-formalization` skill,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git。请读取 `.agent.md`,安装其中声明的 Skill entrypoint,验证 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 ``` 如果你已经有这个 skill 仓库的本地文件夹,把链接换成本地路径即可。clone、link、配置、reload/restart 检查和验证都交给 coding agent 处理。 diff --git a/skills/lean-formalization/README.md b/skills/lean-formalization/README.md new file mode 100644 index 0000000..7709450 --- /dev/null +++ b/skills/lean-formalization/README.md @@ -0,0 +1,30 @@ +# Lean Formalization + +`lean-formalization` is the concrete AI4Math skill package for Lean 4 +formalization, proof repair, theorem transcription, `sorry` completion, Lean +patch review, local validation, and optional official Numina runtime work. + +## Entry Point + +Start with [`SKILL.md`](SKILL.md). It defines the coding-agent-first workflow, +the optional Numina boundary, safety rules, and the reference files to load for +specific tasks. + +## Package Layout + +- `scripts/`: helper CLI commands for environment checks, validation, patch + review, Numina setup, and delivery verification. +- `references/`: task-specific guidance for direct Lean workflows, runtime + configuration, Numina, review, and failure reporting. +- `prompts/`: reusable task envelopes for formalization, proof repair, and + `sorry` completion. +- `config/` and `schemas/`: example configuration and validation schemas. +- `tests/`: package-level Python tests for the helper CLI and validation logic. + +## Validation + +Run from the repository root: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +``` From 421fd7557579731a88e53abc9b65cda3f265b50d Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 14:21:23 +0800 Subject: [PATCH 30/37] Add README references --- README.md | 18 ++++++++++++++++++ README.zh-CN.md | 17 +++++++++++++++++ skills/lean-formalization/README.md | 13 +++++++++++++ 3 files changed, 48 insertions(+) diff --git a/README.md b/README.md index 916add9..34c47c8 100644 --- a/README.md +++ b/README.md @@ -126,3 +126,21 @@ For a full local Lean workspace check: ```bash PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` + +## References + +This skill learns from public Lean and Lean-agent systems, while keeping its own +coding-agent-first workflow and local validation boundary: + +- [Lean](https://lean-lang.org/) and [Lean 4](https://github.com/leanprover/lean4) +- [mathlib4](https://github.com/leanprover-community/mathlib4) +- [Numina Lean Agent](https://github.com/project-numina/numina-lean-agent) +- [Numina Putnam 2025](https://github.com/project-numina/Numina-Putnam2025) +- [LeanDojo](https://github.com/lean-dojo/LeanDojo) and [ReProver](https://github.com/lean-dojo/ReProver) +- [LeanCopilot](https://github.com/lean-dojo/LeanCopilot) +- [lean-lsp-mcp](https://github.com/project-numina/lean-lsp-mcp) +- [COPRA](https://github.com/trishullab/copra) + +These references are used as public design inspiration for setup, proof-state +loops, retrieval, validation, and failure handoff. This project does not claim to +reproduce or replace the original systems. diff --git a/README.zh-CN.md b/README.zh-CN.md index 8a04a9c..582dde5 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -73,3 +73,20 @@ claim 前都应先问用户。 ```bash PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` + +## 参考来源 + +这个 skill 会学习公开 Lean 生态和 Lean-agent 系统中的有效机制,同时保持自己的 +coding-agent-first 工作流和本地 Lean 验证边界: + +- [Lean](https://lean-lang.org/) 和 [Lean 4](https://github.com/leanprover/lean4) +- [mathlib4](https://github.com/leanprover-community/mathlib4) +- [Numina Lean Agent](https://github.com/project-numina/numina-lean-agent) +- [Numina Putnam 2025](https://github.com/project-numina/Numina-Putnam2025) +- [LeanDojo](https://github.com/lean-dojo/LeanDojo) 和 [ReProver](https://github.com/lean-dojo/ReProver) +- [LeanCopilot](https://github.com/lean-dojo/LeanCopilot) +- [lean-lsp-mcp](https://github.com/project-numina/lean-lsp-mcp) +- [COPRA](https://github.com/trishullab/copra) + +这些项目是公开设计参考,主要用于学习 setup、proof-state loop、retrieval、 +validation 和 failure handoff 等机制;本项目不声称复刻或替代原系统。 diff --git a/skills/lean-formalization/README.md b/skills/lean-formalization/README.md index 7709450..8b4bb60 100644 --- a/skills/lean-formalization/README.md +++ b/skills/lean-formalization/README.md @@ -28,3 +28,16 @@ Run from the repository root: ```bash PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` + +## References + +This package learns from public Lean ecosystem and Lean-agent projects: + +- [Lean](https://lean-lang.org/) and [mathlib4](https://github.com/leanprover-community/mathlib4) +- [Numina Lean Agent](https://github.com/project-numina/numina-lean-agent) +- [LeanDojo](https://github.com/lean-dojo/LeanDojo), [ReProver](https://github.com/lean-dojo/ReProver), and [LeanCopilot](https://github.com/lean-dojo/LeanCopilot) +- [lean-lsp-mcp](https://github.com/project-numina/lean-lsp-mcp) +- [COPRA](https://github.com/trishullab/copra) + +They are public design references, not bundled dependencies or claims of +compatibility. From a0dcc250a0995a6d5934142e89d49e588e090db6 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 14:29:02 +0800 Subject: [PATCH 31/37] Use formal related-work wording --- README.md | 18 ++++++++++-------- README.zh-CN.md | 15 ++++++++------- skills/lean-formalization/README.md | 8 ++++---- skills/lean-formalization/SKILL.md | 6 +++--- skills/lean-formalization/agents/openai.yaml | 4 ++-- .../references/direct_lean_workflow.md | 2 +- .../references/interactive_orchestration.md | 2 +- .../references/numina_reverse_analysis.md | 8 ++++---- .../references/specialist_agent_patterns.md | 10 +++++----- .../scripts/verify_delivery.py | 6 +++--- 10 files changed, 41 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 34c47c8..c0701d7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Chinese guide: [README.zh-CN.md](README.zh-CN.md) -`lean-formalization` helps a coding agent work with Lean 4 formalization, proof repair, and validation tasks. It is coding-agent-first, but it learns from and integrates useful patterns from Lean-specialist agents such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. +`lean-formalization` is a coding-agent-first skill package for Lean 4 formalization, proof repair, and validation. Its design is informed by publicly available Lean-specialist agent patterns from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. ## When To Use It @@ -55,7 +55,7 @@ Constraints: - Theorem formalization, proof repair, proof completion, and `sorry` completion. - Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. - Minimal failing Lean fragment extraction when a proof is blocked. -- Learned Lean-specialist agent patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. +- Integrated Lean-specialist agent patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. - Optional official `project-numina/numina-lean-agent` deployment/call flow, mediated by the coding agent. Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `~/.ai4math/numina-runtime/` by default. @@ -127,10 +127,11 @@ For a full local Lean workspace check: PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` -## References +## Related Work and Public References -This skill learns from public Lean and Lean-agent systems, while keeping its own -coding-agent-first workflow and local validation boundary: +This project is informed by the following public Lean ecosystem projects and +Lean-agent systems, while maintaining its own coding-agent-first workflow and +local validation boundary: - [Lean](https://lean-lang.org/) and [Lean 4](https://github.com/leanprover/lean4) - [mathlib4](https://github.com/leanprover-community/mathlib4) @@ -141,6 +142,7 @@ coding-agent-first workflow and local validation boundary: - [lean-lsp-mcp](https://github.com/project-numina/lean-lsp-mcp) - [COPRA](https://github.com/trishullab/copra) -These references are used as public design inspiration for setup, proof-state -loops, retrieval, validation, and failure handoff. This project does not claim to -reproduce or replace the original systems. +These references are cited for related-work context and design provenance around +setup, proof-state loops, retrieval, validation, and failure handoff. Unless +explicitly stated, this repository does not vendor, reproduce, replace, or claim +compatibility with the original systems. diff --git a/README.zh-CN.md b/README.zh-CN.md index 582dde5..1c313bc 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,7 +2,7 @@ [English](README.md) | 简体中文 -`lean-formalization` 帮助 coding agent 处理 Lean 4 形式化、proof repair 和 validation 任务。它是 coding-agent-first,但会学习并整合 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 的有效机制。 +`lean-formalization` 是面向 coding agent 的 Lean 4 形式化、proof repair 和 validation skill package。本项目采用 coding-agent-first 定位,设计参考并整合了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。 ## 适合什么任务 @@ -25,7 +25,7 @@ Agent 应产出 Lean patches、validation summaries、blocked-goal explanations 请帮我安装 `lean-formalization` skill,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git。请读取 `.agent.md`,安装其中声明的 Skill entrypoint,验证 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 ``` -如果你已经有这个 skill 仓库的本地文件夹,把链接换成本地路径即可。clone、link、配置、reload/restart 检查和验证都交给 coding agent 处理。 +如果你已经有本仓库的本地文件夹,把链接换成本地路径即可。clone、link、配置、reload/restart 检查和验证都交给 coding agent 处理。 ## 快速开始 @@ -66,7 +66,7 @@ claim 前都应先问用户。 - patch review:检查 `sorry`、`admit`、新引入的 `axiom` 和 theorem statement drift。 - 可选 official `project-numina/numina-lean-agent` runtime 设置和调用。 - proof blocked 时抽取最小失败 Lean fragment。 -- 学习并整合 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 +- 参考并整合 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 ## 维护者检查 @@ -74,9 +74,9 @@ claim 前都应先问用户。 PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` -## 参考来源 +## 相关工作与公开参考 -这个 skill 会学习公开 Lean 生态和 Lean-agent 系统中的有效机制,同时保持自己的 +本项目设计参考以下公开 Lean 生态项目和 Lean-agent 系统,同时保持自己的 coding-agent-first 工作流和本地 Lean 验证边界: - [Lean](https://lean-lang.org/) 和 [Lean 4](https://github.com/leanprover/lean4) @@ -88,5 +88,6 @@ coding-agent-first 工作流和本地 Lean 验证边界: - [lean-lsp-mcp](https://github.com/project-numina/lean-lsp-mcp) - [COPRA](https://github.com/trishullab/copra) -这些项目是公开设计参考,主要用于学习 setup、proof-state loop、retrieval、 -validation 和 failure handoff 等机制;本项目不声称复刻或替代原系统。 +这些项目用于说明相关工作和设计来源,主要涉及 setup、proof-state loop、 +retrieval、validation 和 failure handoff 等机制。除非另有明确说明,本仓库不 +内置、不复刻、不替代,也不声称兼容原系统。 diff --git a/skills/lean-formalization/README.md b/skills/lean-formalization/README.md index 8b4bb60..6784d26 100644 --- a/skills/lean-formalization/README.md +++ b/skills/lean-formalization/README.md @@ -29,9 +29,9 @@ Run from the repository root: PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` -## References +## Related Work and Public References -This package learns from public Lean ecosystem and Lean-agent projects: +This package is informed by public Lean ecosystem and Lean-agent projects: - [Lean](https://lean-lang.org/) and [mathlib4](https://github.com/leanprover-community/mathlib4) - [Numina Lean Agent](https://github.com/project-numina/numina-lean-agent) @@ -39,5 +39,5 @@ This package learns from public Lean ecosystem and Lean-agent projects: - [lean-lsp-mcp](https://github.com/project-numina/lean-lsp-mcp) - [COPRA](https://github.com/trishullab/copra) -They are public design references, not bundled dependencies or claims of -compatibility. +They are cited as related work and design provenance, not bundled dependencies +or claims of compatibility. diff --git a/skills/lean-formalization/SKILL.md b/skills/lean-formalization/SKILL.md index 36dcf96..2fd2dee 100644 --- a/skills/lean-formalization/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -9,7 +9,7 @@ Use this skill when the user wants a coding agent to do Lean 4 formalization, pr This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker. It reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, preserves theorem statements, and iterates with the user. Default execution mode is coding-agent mode. -Learn from Lean-specialist agent patterns and integrate them into the default coding-agent workflow. Learn from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents by abstracting their mechanisms: project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Use specialist-agent patterns as mechanisms, not mandatory external services. +Incorporate publicly documented Lean-specialist agent patterns into the default coding-agent workflow. Use systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents as related-work references for mechanisms such as project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Treat specialist-agent patterns as mechanisms, not mandatory external services. Official Numina is an optional deployable subagent backend. Keep the official Numina deployment/call path available for users who ask for the official Lean Agent, batch proof search, or an external subagent run. Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run. @@ -38,7 +38,7 @@ Do not remove the official Numina subagent path. Treat it as an optional backend 7. When reporting readiness, lead with local Lean readiness, then Numina subagent readiness. If Numina credentials are missing, say that only the optional Numina subagent path needs configuration. 8. Before a Numina setup or run, inspect `doctor` readiness, explain the deployment/call, target project, prompt, result directory, credential/proxy/MCP state, and local validation plan; proceed only after approval. 9. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. -10. Edit Lean directly in small steps for the default coding-agent path, using learned specialist-agent patterns such as theorem-state inspection, nearby lemma retrieval, bounded proof attempts, failed-strategy notes, and minimal failure extraction. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. +10. Edit Lean directly in small steps for the default coding-agent path, using incorporated specialist-agent patterns such as theorem-state inspection, nearby lemma retrieval, bounded proof attempts, failed-strategy notes, and minimal failure extraction. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. 11. Preserve theorem statements unless the user explicitly approves a change. 12. Reject final patches that contain `sorry`, `admit`, or newly introduced `axiom`. 13. If blocked, stop cleanly with the smallest useful failing Lean fragment, exact errors/goals, and the next mathematical decision needed. @@ -85,4 +85,4 @@ When using the official Numina runtime, follow `references/numina_runtime.md`. F - Read `references/interactive_orchestration.md` when guiding user intake and task decomposition. - Read `references/review_checklist.md` before accepting a Lean patch. - Read `references/failure_taxonomy.md` when reporting a blocked proof. -- Read `references/numina_reverse_analysis.md` when explaining which Numina mechanisms were learned and which are delegated to the optional official runtime. +- Read `references/numina_reverse_analysis.md` when explaining which Numina mechanisms are incorporated locally and which are delegated to the optional official runtime. diff --git a/skills/lean-formalization/agents/openai.yaml b/skills/lean-formalization/agents/openai.yaml index 4c43317..88540b8 100644 --- a/skills/lean-formalization/agents/openai.yaml +++ b/skills/lean-formalization/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: Lean Formalization -short_description: Interactive Lean 4 verification for coding agents that learn from Lean-specialist agent patterns, with optional official Numina subagent calls. -default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。这个 skill 会学习并整合 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 等 Lean 专用 agent 的机制:项目门禁、statement normalization、theorem-state loop、premise retrieval、bounded search、失败记忆、Lean/Lake oracle 和 minimal failure handoff。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 +short_description: Interactive Lean 4 verification for coding agents that incorporate Lean-specialist agent patterns, with optional official Numina subagent calls. +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。该 skill 参考并整合 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 等公开 Lean 专用 agent 的机制:项目门禁、statement normalization、theorem-state loop、premise retrieval、bounded search、失败记忆、Lean/Lake oracle 和 minimal failure handoff。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 diff --git a/skills/lean-formalization/references/direct_lean_workflow.md b/skills/lean-formalization/references/direct_lean_workflow.md index d5ef9a9..aeb3d22 100644 --- a/skills/lean-formalization/references/direct_lean_workflow.md +++ b/skills/lean-formalization/references/direct_lean_workflow.md @@ -1,6 +1,6 @@ # Direct Coding-Agent Lean Workflow -This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. It learns from Lean-specialist agent patterns and integrates them into local work: theorem-state loops, premise retrieval, bounded proof attempts, failed-strategy memory, and minimal failure handoff. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. +This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. It incorporates Lean-specialist agent patterns into local work: theorem-state loops, premise retrieval, bounded proof attempts, failed-strategy memory, and minimal failure handoff. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. ## Guidance-First Loop diff --git a/skills/lean-formalization/references/interactive_orchestration.md b/skills/lean-formalization/references/interactive_orchestration.md index 8ac99da..bd85e4d 100644 --- a/skills/lean-formalization/references/interactive_orchestration.md +++ b/skills/lean-formalization/references/interactive_orchestration.md @@ -1,6 +1,6 @@ # Interactive Orchestration -The coordinating coding agent owns user interaction, Lean proof/formalization work, learned Lean-specialist agent patterns, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. +The coordinating coding agent owns user interaction, Lean proof/formalization work, incorporated Lean-specialist agent patterns, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. This reference covers the guidance layer: session opening, intake, task classification, direct coding-agent Lean work, specialist-agent pattern selection, optional Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. diff --git a/skills/lean-formalization/references/numina_reverse_analysis.md b/skills/lean-formalization/references/numina_reverse_analysis.md index d61ace4..f26dcd8 100644 --- a/skills/lean-formalization/references/numina_reverse_analysis.md +++ b/skills/lean-formalization/references/numina_reverse_analysis.md @@ -1,6 +1,6 @@ -# Numina and Lean-Specialist Agent Learning +# Numina and Lean-Specialist Agent Pattern Integration -This reference records what this coding-agent Lean skill learns from the public Numina Lean Agent workflow, and how those lessons fit the broader Lean-specialist agent pattern library in `specialist_agent_patterns.md`. For deployment/call instructions, use `numina_runtime.md`. +This reference records how this coding-agent Lean skill incorporates mechanisms from the public Numina Lean Agent workflow, and how those mechanisms fit the broader Lean-specialist agent pattern library in `specialist_agent_patterns.md`. For deployment/call instructions, use `numina_runtime.md`. ## Source Scope @@ -8,9 +8,9 @@ This reference records what this coding-agent Lean skill learns from the public - Result repository: https://github.com/project-numina/Numina-Putnam2025 - Paper reference: https://arxiv.org/abs/2601.14027 -The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to learn reusable Lean-agent mechanisms and integrate them into a comprehensive coding-agent skill while preserving a deployable path to the official Numina runtime when the user wants a subagent. +The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to incorporate reusable Lean-agent mechanisms into a comprehensive coding-agent skill while preserving a deployable path to the official Numina runtime when the user wants a subagent. -## Learned Patterns +## Incorporated Patterns 1. Use a coding agent as the primary Lean worker, with Numina available as an optional subagent. 2. Keep Lean/Lake validation as the correctness oracle. diff --git a/skills/lean-formalization/references/specialist_agent_patterns.md b/skills/lean-formalization/references/specialist_agent_patterns.md index 9621b3f..8f01667 100644 --- a/skills/lean-formalization/references/specialist_agent_patterns.md +++ b/skills/lean-formalization/references/specialist_agent_patterns.md @@ -1,6 +1,6 @@ -# Lean-Specialist Agent Pattern Learning +# Lean-Specialist Agent Pattern Integration -This reference explains how the coding-agent-first skill learns from Lean-specialist agent designs without making any external agent mandatory. Preserve the mechanism, not prompts, benchmark-specific assumptions, or private implementation details. +This reference explains how the coding-agent-first skill incorporates publicly documented Lean-specialist agent designs without making any external agent mandatory. Preserve the mechanism, not prompts, benchmark-specific assumptions, or private implementation details. ## Source Families @@ -11,7 +11,7 @@ This reference explains how the coding-agent-first skill learns from Lean-specia - Lean LSP/MCP-style integration: editor/server feedback, goal inspection, diagnostics, and tool scope tied to the target project. - Lightweight iterative agents: small edit/check loops, local context retrieval, and explicit stop conditions. -These sources are patterns to learn from and integrate. Do not claim parity with a specialist prover unless the original backend is actually called and validated. +These sources provide patterns to adapt and integrate. Do not claim parity with a specialist prover unless the original backend is actually called and validated. Public source anchors: @@ -20,7 +20,7 @@ Public source anchors: - LeanCopilot: `https://github.com/lean-dojo/LeanCopilot` - COPRA: `https://github.com/trishullab/copra` -## Learned Default Workflow +## Integrated Default Workflow 1. Gate the project: identify the Lake root, toolchain, mathlib revision, imports, and build status before proof work. 2. Normalize the target: locate the authoritative theorem statement, declaration name, hypotheses, namespace, and allowed statement changes. @@ -47,7 +47,7 @@ Public source anchors: ## Escalation Rule -Default to learned local patterns. Escalate to a real specialist backend only when: +Default to integrated local patterns. Escalate to a real specialist backend only when: - the user asks for Numina, official Lean Agent, batch proof search, or an external subagent; - local bounded attempts are cycling and the user approves a backend call; diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py index 528d0e2..6c2a5f1 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -115,8 +115,8 @@ def _guidance_first_check() -> dict[str, Any]: "The coding agent is the primary Lean worker.", "Official Numina is an optional deployable subagent backend.", "Default execution mode is coding-agent mode.", - "Learn from Lean-specialist agent patterns and integrate them into the default coding-agent workflow.", - "Use specialist-agent patterns as mechanisms, not mandatory external services.", + "Incorporate publicly documented Lean-specialist agent patterns into the default coding-agent workflow.", + "Treat specialist-agent patterns as mechanisms, not mandatory external services.", "Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run.", "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", @@ -156,7 +156,7 @@ def _guidance_first_check() -> dict[str, Any]: "请用中文开始", "如果用户明确使用其他语言", "默认走 coding agent Lean 工作流", - "这个 skill 会学习并整合", + "该 skill 参考并整合", "Numina 是可部署的可选 subagent", ] openai_missing = [phrase for phrase in openai_required if phrase not in openai_yaml] From 93643bb4bdf061d361a039df16c8b25f1bbe3630 Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 14:58:57 +0800 Subject: [PATCH 32/37] Add Lean setup skill entrypoint --- .agent.md | 24 +++++----- AGENTS.md | 2 + CLAUDE.md | 9 +++- GEMINI.md | 7 +++ README.md | 44 +++++++++++------ README.zh-CN.md | 42 ++++++++++++---- SKILL.md | 9 +++- skills/lean-formalization/SKILL.md | 2 + .../scripts/verify_delivery.py | 40 ++++++++++++++++ skills/lean-formalization/tests/test_cli.py | 2 + skills/lean-setup/SKILL.md | 48 +++++++++++++++++++ skills/lean-setup/agents/openai.yaml | 3 ++ 12 files changed, 194 insertions(+), 38 deletions(-) create mode 100644 skills/lean-setup/SKILL.md create mode 100644 skills/lean-setup/agents/openai.yaml diff --git a/.agent.md b/.agent.md index 09107cd..f23a256 100644 --- a/.agent.md +++ b/.agent.md @@ -1,28 +1,30 @@ -# lean-formalization Coding Agent Install Guide +# AI4Math Lean Skills Coding Agent Install Guide -Use this file when a coding agent is asked to install `lean-formalization` interactively. -The shared Skill layer is the source of truth; platform adapters should only -help the active agent find and load that Skill layer. +Use this file when a coding agent is asked to install `lean-setup` or `lean-formalization` interactively. +The shared Skill layers are the source of truth; platform adapters should only +help the active agent find and load those Skill layers. ## Source - Repository: https://github.com/VeryMath/AI4Math-Lean-Agents.git - Branch: `feature/numina-runtime-delivery` -- Skill entrypoint: `skills/lean-formalization/SKILL.md` -- This skill is standalone. Do not require the user to clone - `AI4Math-Skill-Library` just to use it. +- Skill entrypoints: + - `skills/lean-setup/SKILL.md` + - `skills/lean-formalization/SKILL.md` +- These skills are standalone. Do not require the user to clone + `AI4Math-Skill-Library` just to use them. ## Interactive Install Flow 1. Accept either a repository URL/branch or a local folder from the user. 2. If the source is remote, clone or fetch the requested branch into an appropriate workspace. If the source is local, use that folder directly. -3. Inspect `AGENTS.md`, `SKILL.md`, and the declared Skill entrypoint before +3. Inspect `AGENTS.md`, `SKILL.md`, and the declared Skill entrypoints before changing any configuration. 4. Detect the active coding-agent environment and its skill/config location. -5. Install or link the smallest directory that exposes the intended `SKILL.md`. +5. Install or link the smallest directories that expose the intended `SKILL.md` files. Preserve existing configuration and do not overwrite unrelated files. 6. Do not write API keys, tokens, or private credentials into repository files. 7. Reload or restart the target agent only when its discovery mechanism requires - it, then verify that `$lean-formalization` is discoverable. -8. Report the installed source, entrypoint, verification result, and any restart still required. + it, then verify that `$lean-setup` and `$lean-formalization` are discoverable. +8. Report the installed source, entrypoints, verification result, and any restart still required. diff --git a/AGENTS.md b/AGENTS.md index 3ccfee0..d48d0a8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,11 +1,13 @@ # Agent Instructions +Use `skills/lean-setup/SKILL.md` for setup-only tasks such as installing or verifying Lean 4, `elan`, `lake`, or a reusable mathlib workspace. Use the canonical shared Skill layer at `skills/lean-formalization/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. Core rules: - This is a coding-agent-first Lean skill. - The coding agent is the primary Lean worker. +- Setup-only mode should not ask for a theorem target. - Official Numina is an optional deployable subagent backend. - Match the user's language by default. - If the user's language is ambiguous, default to Chinese. diff --git a/CLAUDE.md b/CLAUDE.md index e6d3af1..889df6f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,12 +1,19 @@ # Claude Code Instructions -For Lean work in this repository, read and follow the shared Skill layer: +For Lean setup-only work in this repository, read and follow: + +```text +skills/lean-setup/SKILL.md +``` + +For Lean formalization or proof work in this repository, read and follow the shared Skill layer: ```text skills/lean-formalization/SKILL.md ``` Use Claude Code as the primary Lean coding agent. Official Numina is an optional deployable subagent backend; preserve that setup/call path but do not make it the default. +Setup-only mode should create or verify the Lean/mathlib workspace without asking for a theorem target. Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. diff --git a/GEMINI.md b/GEMINI.md index 5cb7a79..53b613d 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -1,5 +1,11 @@ # Gemini Instructions +For Lean setup-only tasks, use: + +```text +skills/lean-setup/SKILL.md +``` + For Lean 4 formal verification tasks, use the shared Skill layer at: ```text @@ -7,6 +13,7 @@ skills/lean-formalization/SKILL.md ``` Use Gemini as the primary Lean coding agent. Official Numina is an optional deployable subagent backend; preserve that setup/call path but do not make it the default. +Setup-only mode should create or verify the Lean/mathlib workspace without asking for a theorem target. Match the user's language by default. If the user's language is ambiguous, default to Chinese. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. diff --git a/README.md b/README.md index c0701d7..e5c4129 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,25 @@ -# Lean Formalization +# AI4Math Lean Skills Chinese guide: [README.zh-CN.md](README.zh-CN.md) -`lean-formalization` is a coding-agent-first skill package for Lean 4 formalization, proof repair, and validation. Its design is informed by publicly available Lean-specialist agent patterns from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. +This repository provides two AI4Math Lean skills: -## When To Use It +- `lean-setup`: a setup-only entrypoint for Lean 4, `elan`, `lake`, and reusable mathlib workspace readiness. +- `lean-formalization`: a coding-agent-first skill package for Lean 4 formalization, proof repair, and validation. -Use this skill when you have: +`lean-formalization` is informed by publicly available Lean-specialist agent patterns from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. +## When To Use These Skills + +Use these skills when you have: + +- a need to create or verify a Lean/mathlib workspace before proof work (`lean-setup`); - a Lean project or Lean file that needs inspection; - a theorem statement to transcribe or formalize; - a proof with `sorry`, `admit`, errors, or statement drift risk; - a need for optional Numina setup mediated by the coding agent. -## What It Produces +## What They Produce The agent should produce Lean patches, validation summaries, blocked-goal explanations, minimized failures, and optional Numina setup evidence. @@ -22,7 +28,7 @@ The agent should produce Lean patches, validation summaries, blocked-goal explan Copy this to your coding agent: ```text -Please install the `lean-formalization` skill from https://github.com/VeryMath/AI4Math-Lean-Agents.git. Read `.agent.md`, install the declared Skill entrypoint, verify that `$lean-formalization` is discoverable, and tell me whether I need to restart the agent. +Please install the `lean-setup` and `lean-formalization` skills from https://github.com/VeryMath/AI4Math-Lean-Agents.git. Read `.agent.md`, install the declared Skill entrypoints, verify that `$lean-setup` and `$lean-formalization` are discoverable, and tell me whether I need to restart the agent. ``` If you already have this skill repository locally, replace the repository URL @@ -31,6 +37,21 @@ configuration, reload/restart checks, and verification. ## Quick Start +Environment-only setup: + +```text +Use this repository's Lean setup workflow. + +Read: +- AGENTS.md +- skills/lean-setup/SKILL.md + +Goal: +Create or verify a reusable Lean 4/mathlib workspace. +``` + +Formalization or proof work: + ```text Use this repository's Lean workflow. @@ -73,15 +94,8 @@ Numina is optional. The public CLI does not expose a parallel `numina-*` workflo ├── .cursor/ # optional Cursor rule ├── .opencode/ # optional OpenCode agent └── skills/ - └── lean-formalization/ - ├── SKILL.md - ├── agents/ - ├── config/ - ├── prompts/ - ├── references/ - ├── schemas/ - ├── scripts/ - └── tests/ + ├── lean-setup/ # setup-only entrypoint + └── lean-formalization/ # proof/formalization implementation ``` ## How To Interact diff --git a/README.zh-CN.md b/README.zh-CN.md index 1c313bc..799e296 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,13 +1,19 @@ -# Lean Formalization +# AI4Math Lean Skills [English](README.md) | 简体中文 -`lean-formalization` 是面向 coding agent 的 Lean 4 形式化、proof repair 和 validation skill package。本项目采用 coding-agent-first 定位,设计参考并整合了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。 +本仓库提供两个 AI4Math Lean skills: + +- `lean-setup`:用于 Lean 4、`elan`、`lake` 和可复用 mathlib workspace 的 setup-only 入口。 +- `lean-formalization`:面向 coding agent 的 Lean 4 形式化、proof repair 和 validation skill package。 + +`lean-formalization` 采用 coding-agent-first 定位,设计参考并整合了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。 ## 适合什么任务 当你有这些输入或需求时使用: +- 只想创建或验证 Lean/mathlib 工作区时使用 `lean-setup`; - 需要检查的 Lean project 或 Lean 文件; - 需要转写或形式化的 theorem statement; - 带有 `sorry`、`admit`、errors 或 statement drift 风险的 proof; @@ -22,28 +28,43 @@ Agent 应产出 Lean patches、validation summaries、blocked-goal explanations 把下面这句话发给你的 coding agent: ```text -请帮我安装 `lean-formalization` skill,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git。请读取 `.agent.md`,安装其中声明的 Skill entrypoint,验证 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 +请帮我安装 `lean-setup` 和 `lean-formalization` skills,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git。请读取 `.agent.md`,安装其中声明的 Skill entrypoints,验证 `$lean-setup` 和 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 ``` 如果你已经有本仓库的本地文件夹,把链接换成本地路径即可。clone、link、配置、reload/restart 检查和验证都交给 coding agent 处理。 ## 快速开始 +只配置 Lean 环境和 mathlib 工作区: + +```text +请使用本仓库的 Lean setup 工作流。 + +请先读取: +- AGENTS.md +- skills/lean-setup/SKILL.md + +目标: +创建或验证一个可复用的 Lean 4/mathlib 工作区。 +``` + +形式化或 proof repair: + ```text -Use this repository's Lean workflow. +请使用本仓库的 Lean formalization 工作流。 -Read: +请先读取: - AGENTS.md - SKILL.md - skills/lean-formalization/SKILL.md -Goal: +目标: <描述 Lean formalization、proof repair、theorem transcription 或 validation 任务> -Constraints: -- inspect the Lean project first; -- preserve theorem statements unless approved; -- ask before Numina setup, source edits, or final proof claims. +约束: +- 先检查 Lean project; +- 未获批准前保留 theorem statement; +- 在设置 Numina、编辑源码或接受最终 proof claim 前先请求确认。 ``` ## 如何交互使用 @@ -62,6 +83,7 @@ claim 前都应先问用户。 ## 支持范围 - Lean project/workspace inspection。 +- 只配置环境时,可创建或复用共享 `~/.ai4math/lean-workspace`。 - theorem formalization、proof repair、proof completion 和 `sorry` completion。 - patch review:检查 `sorry`、`admit`、新引入的 `axiom` 和 theorem statement drift。 - 可选 official `project-numina/numina-lean-agent` runtime 设置和调用。 diff --git a/SKILL.md b/SKILL.md index 8714221..5e96286 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,6 +1,6 @@ --- name: lean-formalization -description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, Numina runtime setup, or local Lean validation. +description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, Lean environment setup, Numina runtime setup, or local Lean validation. --- # Lean Formalization @@ -15,6 +15,13 @@ skills/lean-formalization/SKILL.md Read that concrete Skill before Lean work. Keep platform adapters thin and improve the shared Skill layer first. +For setup-only tasks such as installing Lean, checking `elan`/`lake`, or creating +a reusable mathlib workspace, use: + +```text +skills/lean-setup/SKILL.md +``` + ## Operating Boundary - Preserve theorem statements unless the user approves a change. diff --git a/skills/lean-formalization/SKILL.md b/skills/lean-formalization/SKILL.md index 2fd2dee..02ab218 100644 --- a/skills/lean-formalization/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -7,6 +7,8 @@ description: Use for interactive Lean 4 formal verification by coding agents wit Use this skill when the user wants a coding agent to do Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or optional official Numina Lean Agent/subagent work. +If the user only wants Lean 4, `elan`, `lake`, or a reusable mathlib workspace configured, use the sibling `../lean-setup/SKILL.md` entrypoint and do not ask for a theorem target. + This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker. It reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, preserves theorem statements, and iterates with the user. Default execution mode is coding-agent mode. Incorporate publicly documented Lean-specialist agent patterns into the default coding-agent workflow. Use systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents as related-work references for mechanisms such as project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Treat specialist-agent patterns as mechanisms, not mandatory external services. diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py index 6c2a5f1..16b6426 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -169,6 +169,43 @@ def _guidance_first_check() -> dict[str, Any]: } +def _lean_setup_entrypoint_check() -> dict[str, Any]: + setup_root = SKILL_ROOT.parent / "lean-setup" + skill_path = setup_root / "SKILL.md" + openai_path = setup_root / "agents" / "openai.yaml" + required_files = [skill_path, openai_path] + if not all(path.exists() for path in required_files): + return { + "ok": False, + "setup_root": str(setup_root), + "missing_files": [str(path) for path in required_files if not path.exists()], + "missing_phrases": [], + "openai_yaml_missing_phrases": [], + } + text = skill_path.read_text(encoding="utf-8", errors="replace") + openai_yaml = openai_path.read_text(encoding="utf-8", errors="replace") + required_phrases = [ + "Use this setup-only entrypoint", + "Do not ask for a theorem target in setup-only mode.", + "The canonical implementation lives in `../lean-formalization/`.", + "python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace", + "Do not require API keys for Lean/mathlib workspace setup.", + "hand off to `lean-formalization`", + ] + openai_required = [ + "不要向用户索要 theorem target", + "所有实现应复用 lean-formalization", + "默认 Lean/mathlib 环境配置不需要 API key", + "应交接到 lean-formalization", + ] + return { + "ok": all(phrase in text for phrase in required_phrases) and all(phrase in openai_yaml for phrase in openai_required), + "setup_root": str(setup_root), + "missing_phrases": [phrase for phrase in required_phrases if phrase not in text], + "openai_yaml_missing_phrases": [phrase for phrase in openai_required if phrase not in openai_yaml], + } + + def verify( cwd: str | Path = ".", require_environment: bool = False, @@ -219,12 +256,14 @@ def verify( hygiene = _package_hygiene() guidance_first = _guidance_first_check() + lean_setup_entrypoint = _lean_setup_entrypoint_check() checks = { "required_files": all(item["exists"] for item in files), "required_commands": REQUIRED_COMMANDS.issubset(commands), "no_parallel_numina_commands": not any(command.startswith("numina") for command in commands), "schemas": all(item["ok"] for item in schemas), "guidance_first_skill": bool(guidance_first.get("ok")), + "lean_setup_entrypoint": bool(lean_setup_entrypoint.get("ok")), "dry_run_prove": bool(dry_run.get("ok") and dry_run.get("status") == "dry_run"), "patch_guard": bool(not review.get("ok") and review.get("findings")), "minimal_failure": bool(failure.get("ok") and failure.get("minimal_failure", {}).get("snippet")), @@ -255,6 +294,7 @@ def verify( }, "schemas": schemas, "guidance_first_skill": guidance_first, + "lean_setup_entrypoint": lean_setup_entrypoint, "dry_run_prove": { "ok": dry_run.get("ok"), "status": dry_run.get("status"), diff --git a/skills/lean-formalization/tests/test_cli.py b/skills/lean-formalization/tests/test_cli.py index c2ea4d8..2704fef 100644 --- a/skills/lean-formalization/tests/test_cli.py +++ b/skills/lean-formalization/tests/test_cli.py @@ -147,6 +147,8 @@ def test_verify_delivery_package_checks(self) -> None: self.assertTrue(payload["ok"]) self.assertEqual(payload["status"], "delivery_ready") self.assertIn("verify-delivery", payload["commands"]["available"]) + self.assertTrue(payload["checks"]["lean_setup_entrypoint"]) + self.assertFalse(payload["lean_setup_entrypoint"]["missing_phrases"]) if __name__ == "__main__": diff --git a/skills/lean-setup/SKILL.md b/skills/lean-setup/SKILL.md new file mode 100644 index 0000000..bcd15eb --- /dev/null +++ b/skills/lean-setup/SKILL.md @@ -0,0 +1,48 @@ +--- +name: lean-setup +description: Use when a coding agent needs to install or verify Lean 4, elan, lake, create or reuse a mathlib workspace, configure a shared Lean environment, or run Lean readiness checks before formalization. +--- + +# Lean Setup + +Use this setup-only entrypoint when the user only wants a Lean 4 environment, `elan`/`lake` readiness, or a reusable mathlib workspace. Do not ask for a theorem target in setup-only mode. + +The canonical implementation lives in `../lean-formalization/`. This skill must reuse the same helper CLI, configuration rules, and runtime references rather than duplicating setup logic. + +## Setup-Only Flow + +1. Match the user's language by default; if ambiguous, default to Chinese. +2. Inspect tool and workspace readiness with `doctor` or `env`. +3. Prefer an existing Lake project when the user points to one. +4. For standalone future Lean work, create or reuse `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. +5. Create the workspace only after explaining that Lean/mathlib artifacts may be downloaded or built. +6. Run the bundled smoke test after setup. +7. Report the installed tools, workspace path, Lean toolchain, mathlib revision when available, smoke-test result, and any remaining action. +8. If the user next wants formalization, proof repair, theorem transcription, `sorry` completion, patch review, or Numina proof search, hand off to `lean-formalization`. + +## Commands + +Run from the repository root: + +```bash +python skills/lean-formalization/scripts/ai4m_lean.py doctor --cwd . +python skills/lean-formalization/scripts/ai4m_lean.py env --cwd . +python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace +python skills/lean-formalization/scripts/ai4m_lean.py smoke-test --cwd . +``` + +Use `--dry-run` before setup when the user wants to review commands. + +## Boundaries + +- Do not create a second setup implementation. +- Do not change a user project's `lean-toolchain` or mathlib revision without approval. +- Do not require API keys for Lean/mathlib workspace setup. +- Do not configure or call official Numina unless the user explicitly asks for that optional backend. +- Do not commit machine-specific paths, downloaded runtime state, or secrets. + +## References + +- Read `../lean-formalization/references/lean_runtime_configuration.md` for shared workspace layout, local configuration, and version policy. +- Read `../lean-formalization/references/numina_runtime.md` only when the user asks for optional official Numina setup. +- Use `../lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests` for package validation. diff --git a/skills/lean-setup/agents/openai.yaml b/skills/lean-setup/agents/openai.yaml new file mode 100644 index 0000000..99aabc3 --- /dev/null +++ b/skills/lean-setup/agents/openai.yaml @@ -0,0 +1,3 @@ +display_name: Lean Setup +short_description: Lean 4, elan, lake, and reusable mathlib workspace setup for coding agents. +default_prompt: 请默认使用中文,并主动完成 Lean 环境配置引导;仅当用户明确使用其他语言时切换。该入口仅用于 setup-only 任务:检查或安装 Lean/elan/lake,创建或复用带 mathlib 的共享工作区,运行 smoke-test,并报告 workspace 路径、toolchain、mathlib revision、验证结果与剩余动作。不要向用户索要 theorem target。所有实现应复用 lean-formalization 的 helper CLI 与 runtime references,不复制第二套配置逻辑。默认 Lean/mathlib 环境配置不需要 API key;只有在用户明确要求 optional official Numina backend 时,才说明凭据需求并请求批准。配置完成后,如用户要进行形式化、proof repair、sorry completion 或 Numina proof search,应交接到 lean-formalization。 From d38a1e656a7f0bb8da4381311e7f58d40bac380c Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 16:14:09 +0800 Subject: [PATCH 33/37] Tighten Lean setup skill boundaries --- AGENTS.md | 3 +- CLAUDE.md | 3 +- GEMINI.md | 3 +- README.md | 4 +- README.zh-CN.md | 54 ++++++++++-- SKILL.md | 6 +- .../scripts/verify_delivery.py | 87 ++++++++++++++++--- skills/lean-formalization/tests/test_cli.py | 26 ++++++ skills/lean-setup/SKILL.md | 23 ++--- 9 files changed, 170 insertions(+), 39 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d48d0a8..5862bb5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,7 +15,8 @@ Core rules: - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. - Use the bundled smoke test when no user target is available. -- Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. +- Formalization/proof readiness should inspect local Lean readiness and Numina subagent readiness separately. +- Setup-only readiness should focus on local Lean/mathlib state, and should mention or inspect Numina only when the user asks for the optional official backend. - Do not require API keys for the default coding-agent path. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. - Prefer the user's existing Lake project. Use the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` only when a standalone file needs project context. diff --git a/CLAUDE.md b/CLAUDE.md index 889df6f..570ee16 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,7 +20,8 @@ Lead the interaction: inspect context, summarize what is ready, recommend the ne Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Use the bundled smoke test when no user target is available. -Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. +Formalization/proof readiness should inspect local Lean readiness and Numina subagent readiness separately. +Setup-only readiness should focus on local Lean/mathlib state, and should mention or inspect Numina only when the user asks for the optional official backend. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. diff --git a/GEMINI.md b/GEMINI.md index 53b613d..427b59d 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -20,7 +20,8 @@ Lead the interaction: inspect context, summarize what is ready, recommend the ne Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Use the bundled smoke test when no user target is available. -Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. +Formalization/proof readiness should inspect local Lean readiness and Numina subagent readiness separately. +Setup-only readiness should focus on local Lean/mathlib state, and should mention or inspect Numina only when the user asks for the optional official backend. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. diff --git a/README.md b/README.md index e5c4129..7533f25 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,14 @@ Constraints: - ask before Numina setup, source edits, or final proof claims. ``` -## What It Supports +## What They Support - Lean project/workspace inspection. - Reusable shared `~/.ai4math/lean-workspace` setup for standalone Lean files. - Theorem formalization, proof repair, proof completion, and `sorry` completion. - Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. - Minimal failing Lean fragment extraction when a proof is blocked. -- Integrated Lean-specialist agent patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. +- Related-work-informed Lean-specialist patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. - Optional official `project-numina/numina-lean-agent` deployment/call flow, mediated by the coding agent. Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `~/.ai4math/numina-runtime/` by default. diff --git a/README.zh-CN.md b/README.zh-CN.md index 799e296..74d0485 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -7,11 +7,11 @@ - `lean-setup`:用于 Lean 4、`elan`、`lake` 和可复用 mathlib workspace 的 setup-only 入口。 - `lean-formalization`:面向 coding agent 的 Lean 4 形式化、proof repair 和 validation skill package。 -`lean-formalization` 采用 coding-agent-first 定位,设计参考并整合了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。 +`lean-formalization` 采用 coding-agent-first 定位,设计借鉴了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。 ## 适合什么任务 -当你有这些输入或需求时使用: +适用场景如下: - 只想创建或验证 Lean/mathlib 工作区时使用 `lean-setup`; - 需要检查的 Lean project 或 Lean 文件; @@ -25,13 +25,13 @@ Agent 应产出 Lean patches、validation summaries、blocked-goal explanations ## 安装 -把下面这句话发给你的 coding agent: +将以下安装请求提供给你的 coding agent: ```text 请帮我安装 `lean-setup` 和 `lean-formalization` skills,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git。请读取 `.agent.md`,安装其中声明的 Skill entrypoints,验证 `$lean-setup` 和 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 ``` -如果你已经有本仓库的本地文件夹,把链接换成本地路径即可。clone、link、配置、reload/restart 检查和验证都交给 coding agent 处理。 +如果你已经有本仓库的本地文件夹,可将链接替换为本地路径。coding agent 应负责 clone/link、配置、reload/restart 检查与验证。 ## 快速开始 @@ -78,7 +78,7 @@ Lean 任务 -> 项目检查 -> 计划 -> approve / revise / reject / skip `approve` 表示执行下一步,`revise` 表示先修改计划,`reject` 表示停止当前路线, `skip` 表示跳过当前阶段。修改 theorem statement、设置 Numina、编辑源码和接受最终 proof -claim 前都应先问用户。 +claim 前都应先请求用户确认。 ## 支持范围 @@ -88,7 +88,43 @@ claim 前都应先问用户。 - patch review:检查 `sorry`、`admit`、新引入的 `axiom` 和 theorem statement drift。 - 可选 official `project-numina/numina-lean-agent` runtime 设置和调用。 - proof blocked 时抽取最小失败 Lean fragment。 -- 参考并整合 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 +- 借鉴 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 + +Numina 是可选链路。公共 CLI 不提供并行的 `numina-*` workflow;`doctor` 用于报告 readiness,`configure --setup-numina --project-name ` 用于在 review 后执行本地设置,默认位置为 `~/.ai4math/numina-runtime/`。只有当用户明确要求 `Numina`、`official Lean Agent`、批量 proof search 或外部 subagent run 时,才应进入 official Numina backend。 + +## 仓库结构 + +```text +. +├── AGENTS.md +├── CLAUDE.md +├── GEMINI.md +├── README.md +├── LICENSE +├── .github/ +├── .cursor/ # optional Cursor rule +├── .opencode/ # optional OpenCode agent +└── skills/ + ├── lean-setup/ # setup-only entrypoint + └── lean-formalization/ # proof/formalization implementation +``` + +## 辅助命令 + +在仓库根目录运行: + +```bash +python skills/lean-formalization/scripts/ai4m_lean.py env --cwd . +python skills/lean-formalization/scripts/ai4m_lean.py doctor --cwd . +python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace +python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run +python skills/lean-formalization/scripts/ai4m_lean.py check --cwd . --skip-build +python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +``` + +辅助 CLI 不是 proof engine。coding agent 仍负责读取 Lean errors、编辑 proofs、选择 proof strategy,并匹配用户语言。 + +可选 Numina 路径请读取 `skills/lean-formalization/references/numina_runtime.md`。setup 和 official runner calls 可能 clone repositories、安装工具或使用外部 model/API credentials,因此执行前应先说明。 ## 维护者检查 @@ -96,6 +132,12 @@ claim 前都应先问用户。 PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` +完整本地 Lean workspace 检查: + +```bash +PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +``` + ## 相关工作与公开参考 本项目设计参考以下公开 Lean 生态项目和 Lean-agent 系统,同时保持自己的 diff --git a/SKILL.md b/SKILL.md index 5e96286..3890219 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,6 +1,6 @@ --- name: lean-formalization -description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, Lean environment setup, Numina runtime setup, or local Lean validation. +description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, optional official Numina deployment/calls, or local Lean validation. --- # Lean Formalization @@ -12,8 +12,8 @@ top-level Skill file. The shared Skill layer lives at: skills/lean-formalization/SKILL.md ``` -Read that concrete Skill before Lean work. Keep platform adapters thin and -improve the shared Skill layer first. +Read that concrete Skill before formalization or proof work. Keep platform +adapters thin and improve the shared Skill layer first. For setup-only tasks such as installing Lean, checking `elan`/`lake`, or creating a reusable mathlib workspace, use: diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py index 16b6426..176fdba 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -18,6 +18,7 @@ SKILL_ROOT = Path(__file__).resolve().parents[1] +SKILLS_ROOT = SKILL_ROOT.parent REQUIRED_FILES = [ "SKILL.md", "agents/openai.yaml", @@ -77,9 +78,14 @@ def _load_schema(path: Path) -> dict[str, Any]: def _package_hygiene() -> dict[str, Any]: + package_roots = [SKILL_ROOT] + setup_root = SKILLS_ROOT / "lean-setup" + if setup_root.exists(): + package_roots.append(setup_root) generated = [ - str(path.relative_to(SKILL_ROOT)) - for path in SKILL_ROOT.rglob("*") + str(path.relative_to(SKILLS_ROOT)) + for root in package_roots + for path in root.rglob("*") if "__pycache__" in path.parts or path.suffix == ".pyc" ] suspicious_secret_patterns = [ @@ -88,17 +94,20 @@ def _package_hygiene() -> dict[str, Any]: "BEGIN " + "OPENAI API KEY", ] secret_hits: list[str] = [] - for path in SKILL_ROOT.rglob("*"): - if not path.is_file() or "__pycache__" in path.parts or path.suffix == ".pyc": - continue - try: - text = path.read_text(encoding="utf-8", errors="replace") - except OSError: - continue - if any(pattern in text for pattern in suspicious_secret_patterns): - secret_hits.append(str(path.relative_to(SKILL_ROOT))) + for root in package_roots: + paths = root.rglob("*") + for path in paths: + if not path.is_file() or "__pycache__" in path.parts or path.suffix == ".pyc": + continue + try: + text = path.read_text(encoding="utf-8", errors="replace") + except OSError: + continue + if any(pattern in text for pattern in suspicious_secret_patterns): + secret_hits.append(str(path.relative_to(SKILLS_ROOT))) return { "ok": not secret_hits, + "scanned_roots": [str(path) for path in package_roots], "generated_files": generated, "generated_files_note": "ignored by .gitignore; remove before packaging if creating an archive" if generated else None, "secret_pattern_hits": secret_hits, @@ -169,18 +178,52 @@ def _guidance_first_check() -> dict[str, Any]: } +def _root_discovery_boundary_check() -> dict[str, Any]: + repo_root = SKILLS_ROOT.parent + root_skill = repo_root / "SKILL.md" + if not root_skill.exists(): + return { + "ok": True, + "root_skill": None, + "skipped": True, + "root_setup_only_trigger_hits": [], + } + text = root_skill.read_text(encoding="utf-8", errors="replace") + frontmatter = text.split("---", 2)[1] if text.startswith("---") and text.count("---") >= 2 else text + setup_only_triggers = [ + "Lean environment setup", + "installing Lean", + "install Lean", + "checking elan", + "elan/lake", + "mathlib workspace", + "shared Lean environment", + ] + hits = [phrase for phrase in setup_only_triggers if phrase in frontmatter] + return { + "ok": not hits, + "root_skill": str(root_skill), + "skipped": False, + "root_setup_only_trigger_hits": hits, + } + + def _lean_setup_entrypoint_check() -> dict[str, Any]: - setup_root = SKILL_ROOT.parent / "lean-setup" + setup_root = SKILLS_ROOT / "lean-setup" skill_path = setup_root / "SKILL.md" openai_path = setup_root / "agents" / "openai.yaml" + helper_script = SKILL_ROOT / "scripts" / "ai4m_lean.py" required_files = [skill_path, openai_path] if not all(path.exists() for path in required_files): return { "ok": False, "setup_root": str(setup_root), + "helper_script": str(helper_script), + "helper_script_exists": helper_script.exists(), "missing_files": [str(path) for path in required_files if not path.exists()], "missing_phrases": [], "openai_yaml_missing_phrases": [], + "repo_root_command_hits": [], } text = skill_path.read_text(encoding="utf-8", errors="replace") openai_yaml = openai_path.read_text(encoding="utf-8", errors="replace") @@ -188,10 +231,15 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: "Use this setup-only entrypoint", "Do not ask for a theorem target in setup-only mode.", "The canonical implementation lives in `../lean-formalization/`.", - "python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace", + "../lean-formalization/scripts/ai4m_lean.py", + "Install Lean through the official `elan` channel", "Do not require API keys for Lean/mathlib workspace setup.", "hand off to `lean-formalization`", ] + repo_root_commands = [ + "python skills/lean-formalization/scripts/ai4m_lean.py", + ] + repo_root_command_hits = [phrase for phrase in repo_root_commands if phrase in text] openai_required = [ "不要向用户索要 theorem target", "所有实现应复用 lean-formalization", @@ -199,10 +247,18 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: "应交接到 lean-formalization", ] return { - "ok": all(phrase in text for phrase in required_phrases) and all(phrase in openai_yaml for phrase in openai_required), + "ok": ( + helper_script.exists() + and not repo_root_command_hits + and all(phrase in text for phrase in required_phrases) + and all(phrase in openai_yaml for phrase in openai_required) + ), "setup_root": str(setup_root), + "helper_script": str(helper_script), + "helper_script_exists": helper_script.exists(), "missing_phrases": [phrase for phrase in required_phrases if phrase not in text], "openai_yaml_missing_phrases": [phrase for phrase in openai_required if phrase not in openai_yaml], + "repo_root_command_hits": repo_root_command_hits, } @@ -256,6 +312,7 @@ def verify( hygiene = _package_hygiene() guidance_first = _guidance_first_check() + discovery_boundaries = _root_discovery_boundary_check() lean_setup_entrypoint = _lean_setup_entrypoint_check() checks = { "required_files": all(item["exists"] for item in files), @@ -263,6 +320,7 @@ def verify( "no_parallel_numina_commands": not any(command.startswith("numina") for command in commands), "schemas": all(item["ok"] for item in schemas), "guidance_first_skill": bool(guidance_first.get("ok")), + "discovery_boundaries": bool(discovery_boundaries.get("ok")), "lean_setup_entrypoint": bool(lean_setup_entrypoint.get("ok")), "dry_run_prove": bool(dry_run.get("ok") and dry_run.get("status") == "dry_run"), "patch_guard": bool(not review.get("ok") and review.get("findings")), @@ -294,6 +352,7 @@ def verify( }, "schemas": schemas, "guidance_first_skill": guidance_first, + "discovery_boundaries": discovery_boundaries, "lean_setup_entrypoint": lean_setup_entrypoint, "dry_run_prove": { "ok": dry_run.get("ok"), diff --git a/skills/lean-formalization/tests/test_cli.py b/skills/lean-formalization/tests/test_cli.py index 2704fef..a94079e 100644 --- a/skills/lean-formalization/tests/test_cli.py +++ b/skills/lean-formalization/tests/test_cli.py @@ -12,6 +12,7 @@ sys.path.insert(0, str(SKILL_ROOT / "scripts")) from ai4m_lean import EXIT_LEAN_FAILED, _exit_code # noqa: E402 +from verify_delivery import _lean_setup_entrypoint_check, _package_hygiene, _root_discovery_boundary_check # noqa: E402 CLI = SKILL_ROOT / "scripts" / "ai4m_lean.py" FIXTURES = Path(__file__).resolve().parent / "fixtures" @@ -150,6 +151,31 @@ def test_verify_delivery_package_checks(self) -> None: self.assertTrue(payload["checks"]["lean_setup_entrypoint"]) self.assertFalse(payload["lean_setup_entrypoint"]["missing_phrases"]) + def test_root_discovery_does_not_steal_setup_only_tasks(self) -> None: + boundary = _root_discovery_boundary_check() + self.assertTrue(boundary["ok"], boundary) + self.assertFalse(boundary["root_setup_only_trigger_hits"]) + + def test_lean_setup_entrypoint_uses_sibling_helper_layout(self) -> None: + setup = _lean_setup_entrypoint_check() + self.assertTrue(setup["ok"], setup) + self.assertTrue(setup["helper_script_exists"], setup) + self.assertFalse(setup["repo_root_command_hits"], setup) + + def test_package_hygiene_scans_lean_setup_entrypoint(self) -> None: + generated = SKILL_ROOT.parent / "lean-setup" / "__pycache__" / "sentinel.pyc" + generated.parent.mkdir(exist_ok=True) + try: + generated.write_bytes(b"placeholder") + hygiene = _package_hygiene() + self.assertIn("lean-setup/__pycache__/sentinel.pyc", hygiene["generated_files"]) + finally: + generated.unlink(missing_ok=True) + try: + generated.parent.rmdir() + except OSError: + pass + if __name__ == "__main__": unittest.main() diff --git a/skills/lean-setup/SKILL.md b/skills/lean-setup/SKILL.md index bcd15eb..e31d343 100644 --- a/skills/lean-setup/SKILL.md +++ b/skills/lean-setup/SKILL.md @@ -13,22 +13,23 @@ The canonical implementation lives in `../lean-formalization/`. This skill must 1. Match the user's language by default; if ambiguous, default to Chinese. 2. Inspect tool and workspace readiness with `doctor` or `env`. -3. Prefer an existing Lake project when the user points to one. -4. For standalone future Lean work, create or reuse `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. -5. Create the workspace only after explaining that Lean/mathlib artifacts may be downloaded or built. -6. Run the bundled smoke test after setup. -7. Report the installed tools, workspace path, Lean toolchain, mathlib revision when available, smoke-test result, and any remaining action. -8. If the user next wants formalization, proof repair, theorem transcription, `sorry` completion, patch review, or Numina proof search, hand off to `lean-formalization`. +3. If `elan`, `lean`, or `lake` is missing, explain the required Lean installation step first. Install Lean through the official `elan` channel appropriate for the user's OS after approval; `lean` and `lake` should come from the `elan` toolchain rather than a repository-local copy. +4. Prefer an existing Lake project when the user points to one. +5. For standalone future Lean work, create or reuse `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. +6. Create the workspace only after explaining that Lean/mathlib artifacts may be downloaded or built. +7. Run the bundled smoke test after setup. +8. Report the installed tools, workspace path, Lean toolchain, mathlib revision when available, smoke-test result, and any remaining action. +9. If the user next wants formalization, proof repair, theorem transcription, `sorry` completion, patch review, or Numina proof search, hand off to `lean-formalization`. ## Commands -Run from the repository root: +Resolve the helper from the sibling skill path `../lean-formalization/scripts/ai4m_lean.py`, then run it with `--cwd `. In a source checkout this is the same helper under `skills/lean-formalization/scripts/ai4m_lean.py`. ```bash -python skills/lean-formalization/scripts/ai4m_lean.py doctor --cwd . -python skills/lean-formalization/scripts/ai4m_lean.py env --cwd . -python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace -python skills/lean-formalization/scripts/ai4m_lean.py smoke-test --cwd . +python ../lean-formalization/scripts/ai4m_lean.py doctor --cwd +python ../lean-formalization/scripts/ai4m_lean.py env --cwd +python ../lean-formalization/scripts/ai4m_lean.py configure --cwd --create-workspace +python ../lean-formalization/scripts/ai4m_lean.py smoke-test --cwd ``` Use `--dry-run` before setup when the user wants to review commands. From 2e8f3dcab067e6344dec26f05be8b9a3528ec07a Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 17:05:28 +0800 Subject: [PATCH 34/37] Let users name isolated Lean setup workspaces --- skills/lean-formalization/scripts/verify_delivery.py | 3 +++ skills/lean-formalization/tests/test_cli.py | 6 ++++++ skills/lean-setup/SKILL.md | 11 ++++++----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-formalization/scripts/verify_delivery.py index 176fdba..a833944 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-formalization/scripts/verify_delivery.py @@ -233,6 +233,9 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: "The canonical implementation lives in `../lean-formalization/`.", "../lean-formalization/scripts/ai4m_lean.py", "Install Lean through the official `elan` channel", + "When creating an isolated test directory or workspace", + "suggest a safe default name", + "use the default if the user has no naming preference", "Do not require API keys for Lean/mathlib workspace setup.", "hand off to `lean-formalization`", ] diff --git a/skills/lean-formalization/tests/test_cli.py b/skills/lean-formalization/tests/test_cli.py index a94079e..0780675 100644 --- a/skills/lean-formalization/tests/test_cli.py +++ b/skills/lean-formalization/tests/test_cli.py @@ -162,6 +162,12 @@ def test_lean_setup_entrypoint_uses_sibling_helper_layout(self) -> None: self.assertTrue(setup["helper_script_exists"], setup) self.assertFalse(setup["repo_root_command_hits"], setup) + def test_lean_setup_offers_default_names_for_isolated_setup(self) -> None: + text = (SKILL_ROOT.parent / "lean-setup" / "SKILL.md").read_text(encoding="utf-8") + self.assertIn("When creating an isolated test directory or workspace", text) + self.assertIn("suggest a safe default name", text) + self.assertIn("use the default if the user has no naming preference", text) + def test_package_hygiene_scans_lean_setup_entrypoint(self) -> None: generated = SKILL_ROOT.parent / "lean-setup" / "__pycache__" / "sentinel.pyc" generated.parent.mkdir(exist_ok=True) diff --git a/skills/lean-setup/SKILL.md b/skills/lean-setup/SKILL.md index e31d343..26a7c97 100644 --- a/skills/lean-setup/SKILL.md +++ b/skills/lean-setup/SKILL.md @@ -15,11 +15,12 @@ The canonical implementation lives in `../lean-formalization/`. This skill must 2. Inspect tool and workspace readiness with `doctor` or `env`. 3. If `elan`, `lean`, or `lake` is missing, explain the required Lean installation step first. Install Lean through the official `elan` channel appropriate for the user's OS after approval; `lean` and `lake` should come from the `elan` toolchain rather than a repository-local copy. 4. Prefer an existing Lake project when the user points to one. -5. For standalone future Lean work, create or reuse `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. -6. Create the workspace only after explaining that Lean/mathlib artifacts may be downloaded or built. -7. Run the bundled smoke test after setup. -8. Report the installed tools, workspace path, Lean toolchain, mathlib revision when available, smoke-test result, and any remaining action. -9. If the user next wants formalization, proof repair, theorem transcription, `sorry` completion, patch review, or Numina proof search, hand off to `lean-formalization`. +5. When creating an isolated test directory or workspace, suggest a safe default name and let the user confirm or rename it; use the default if the user has no naming preference. +6. For standalone future Lean work, create or reuse `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. +7. Create the workspace only after explaining that Lean/mathlib artifacts may be downloaded or built. +8. Run the bundled smoke test after setup. +9. Report the installed tools, workspace path, Lean toolchain, mathlib revision when available, smoke-test result, and any remaining action. +10. If the user next wants formalization, proof repair, theorem transcription, `sorry` completion, patch review, or Numina proof search, hand off to `lean-formalization`. ## Commands From a830e1302cce0a6dae73a7b1a8c65125735d7ddc Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 17:33:40 +0800 Subject: [PATCH 35/37] Split Lean skills from shared runtime --- .agent.md | 9 ++- .codex/INSTALL.md | 5 +- .cursor/rules/lean-formalization.mdc | 2 +- .github/workflows/verify.yml | 4 +- .opencode/agents/lean-formalization.md | 6 ++ AGENTS.md | 3 +- CLAUDE.md | 6 ++ GEMINI.md | 2 +- README.md | 25 ++++---- README.zh-CN.md | 25 ++++---- SKILL.md | 6 ++ skills/lean-formalization/README.md | 18 +++--- skills/lean-formalization/SKILL.md | 26 ++++---- .../config/env.example | 0 .../config/lean_agent.example.toml | 0 .../config/numina_runtime.example.toml | 0 .../examples/smoke/NuminaSmoke.lean | 0 .../prompts/complete_sorries.md | 0 .../prompts/formalize_statement.md | 0 .../prompts/prove_theorem.md | 0 .../prompts/repair_lean_file.md | 0 .../references/direct_lean_workflow.md | 0 .../references/failure_taxonomy.md | 0 .../references/interactive_orchestration.md | 0 .../references/lean_runtime_configuration.md | 6 +- .../references/numina_reverse_analysis.md | 0 .../references/numina_runtime.md | 0 .../numina_subagent_troubleshooting.md | 0 .../references/review_checklist.md | 0 .../references/specialist_agent_patterns.md | 0 .../schemas/config.schema.json | 0 .../schemas/result.schema.json | 0 .../schemas/task.schema.json | 0 .../scripts/ai4m_lean.py | 0 .../scripts/check_lean_project.py | 0 .../scripts/common.py | 0 .../scripts/configure_lean.py | 0 .../scripts/detect_sorry.py | 0 .../scripts/direct_task.py | 0 .../scripts/extract_minimal_failure.py | 0 .../scripts/numina_runtime.py | 0 .../scripts/smoke_test.py | 0 .../scripts/tool_status.py | 0 .../scripts/validate_patch.py | 0 .../scripts/verify_delivery.py | 59 +++++++++++-------- .../tests/fixtures/after_bad.lean | 0 .../fixtures/after_statement_changed.lean | 0 .../tests/fixtures/before.lean | 0 .../tests/fixtures/failure.lean | 0 .../tests/test_check_lean_project.py | 0 .../tests/test_cli.py | 12 ++++ .../tests/test_common_config.py | 0 .../tests/test_configure_lean.py | 0 .../tests/test_detect_sorry.py | 0 .../tests/test_direct_task.py | 0 .../tests/test_numina_runtime.py | 0 .../tests/test_validate_patch.py | 0 skills/lean-setup/SKILL.md | 18 +++--- skills/lean-setup/agents/openai.yaml | 2 +- 59 files changed, 142 insertions(+), 92 deletions(-) rename skills/{lean-formalization => lean-runtime}/config/env.example (100%) rename skills/{lean-formalization => lean-runtime}/config/lean_agent.example.toml (100%) rename skills/{lean-formalization => lean-runtime}/config/numina_runtime.example.toml (100%) rename skills/{lean-formalization => lean-runtime}/examples/smoke/NuminaSmoke.lean (100%) rename skills/{lean-formalization => lean-runtime}/prompts/complete_sorries.md (100%) rename skills/{lean-formalization => lean-runtime}/prompts/formalize_statement.md (100%) rename skills/{lean-formalization => lean-runtime}/prompts/prove_theorem.md (100%) rename skills/{lean-formalization => lean-runtime}/prompts/repair_lean_file.md (100%) rename skills/{lean-formalization => lean-runtime}/references/direct_lean_workflow.md (100%) rename skills/{lean-formalization => lean-runtime}/references/failure_taxonomy.md (100%) rename skills/{lean-formalization => lean-runtime}/references/interactive_orchestration.md (100%) rename skills/{lean-formalization => lean-runtime}/references/lean_runtime_configuration.md (89%) rename skills/{lean-formalization => lean-runtime}/references/numina_reverse_analysis.md (100%) rename skills/{lean-formalization => lean-runtime}/references/numina_runtime.md (100%) rename skills/{lean-formalization => lean-runtime}/references/numina_subagent_troubleshooting.md (100%) rename skills/{lean-formalization => lean-runtime}/references/review_checklist.md (100%) rename skills/{lean-formalization => lean-runtime}/references/specialist_agent_patterns.md (100%) rename skills/{lean-formalization => lean-runtime}/schemas/config.schema.json (100%) rename skills/{lean-formalization => lean-runtime}/schemas/result.schema.json (100%) rename skills/{lean-formalization => lean-runtime}/schemas/task.schema.json (100%) rename skills/{lean-formalization => lean-runtime}/scripts/ai4m_lean.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/check_lean_project.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/common.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/configure_lean.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/detect_sorry.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/direct_task.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/extract_minimal_failure.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/numina_runtime.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/smoke_test.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/tool_status.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/validate_patch.py (100%) rename skills/{lean-formalization => lean-runtime}/scripts/verify_delivery.py (90%) rename skills/{lean-formalization => lean-runtime}/tests/fixtures/after_bad.lean (100%) rename skills/{lean-formalization => lean-runtime}/tests/fixtures/after_statement_changed.lean (100%) rename skills/{lean-formalization => lean-runtime}/tests/fixtures/before.lean (100%) rename skills/{lean-formalization => lean-runtime}/tests/fixtures/failure.lean (100%) rename skills/{lean-formalization => lean-runtime}/tests/test_check_lean_project.py (100%) rename skills/{lean-formalization => lean-runtime}/tests/test_cli.py (92%) rename skills/{lean-formalization => lean-runtime}/tests/test_common_config.py (100%) rename skills/{lean-formalization => lean-runtime}/tests/test_configure_lean.py (100%) rename skills/{lean-formalization => lean-runtime}/tests/test_detect_sorry.py (100%) rename skills/{lean-formalization => lean-runtime}/tests/test_direct_task.py (100%) rename skills/{lean-formalization => lean-runtime}/tests/test_numina_runtime.py (100%) rename skills/{lean-formalization => lean-runtime}/tests/test_validate_patch.py (100%) diff --git a/.agent.md b/.agent.md index f23a256..1d3ba32 100644 --- a/.agent.md +++ b/.agent.md @@ -11,8 +11,10 @@ help the active agent find and load those Skill layers. - Skill entrypoints: - `skills/lean-setup/SKILL.md` - `skills/lean-formalization/SKILL.md` -- These skills are standalone. Do not require the user to clone - `AI4Math-Skill-Library` just to use them. +- Shared support layer: + - `skills/lean-runtime/` +- These public skills are standalone from `AI4Math-Skill-Library`, but both + entrypoints require the bundled `skills/lean-runtime/` support directory. ## Interactive Install Flow @@ -22,7 +24,8 @@ help the active agent find and load those Skill layers. 3. Inspect `AGENTS.md`, `SKILL.md`, and the declared Skill entrypoints before changing any configuration. 4. Detect the active coding-agent environment and its skill/config location. -5. Install or link the smallest directories that expose the intended `SKILL.md` files. +5. Install or link the smallest directories that expose the intended `SKILL.md` files, + plus the sibling `lean-runtime` support directory. Preserve existing configuration and do not overwrite unrelated files. 6. Do not write API keys, tokens, or private credentials into repository files. 7. Reload or restart the target agent only when its discovery mechanism requires diff --git a/.codex/INSTALL.md b/.codex/INSTALL.md index ee5ec3f..0b1b2f3 100644 --- a/.codex/INSTALL.md +++ b/.codex/INSTALL.md @@ -8,7 +8,8 @@ skills/lean-formalization/SKILL.md Use from the checkout by asking Codex to read `AGENTS.md`, `SKILL.md`, and the concrete Skill file. For local discovery, sync or link -`skills/lean-formalization/` into the Codex Skill path used by your -installation, then restart or reload if required. +`skills/lean-setup/` and `skills/lean-formalization/` into the Codex Skill path +used by your installation, and keep `skills/lean-runtime/` as their sibling +support directory. Then restart or reload if required. Do not duplicate workflow logic in `.codex/`; update the shared Skill layer. diff --git a/.cursor/rules/lean-formalization.mdc b/.cursor/rules/lean-formalization.mdc index 853cdb8..2a75b04 100644 --- a/.cursor/rules/lean-formalization.mdc +++ b/.cursor/rules/lean-formalization.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/lean-formalization/SKILL.md` as the canonical workflow. -This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker: read/edit Lean, run Lean/Lake, iterate from errors, and validate final patches locally. Official Numina is an optional deployable subagent backend; preserve that deployment/call path but do not make it the default. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/lean-formalization/scripts/` is optional and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker: read/edit Lean, run Lean/Lake, iterate from errors, and validate final patches locally. Official Numina is an optional deployable subagent backend; preserve that deployment/call path but do not make it the default. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/lean-runtime/scripts/` is optional shared tooling and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. Deploy or call the official Numina subagent only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 54f6b80..0323321 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -16,8 +16,8 @@ jobs: - name: Run unit tests run: | - PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/lean-formalization/tests + PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s skills/lean-runtime/tests - name: Verify package shape run: | - PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests + PYTHONDONTWRITEBYTECODE=1 python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests diff --git a/.opencode/agents/lean-formalization.md b/.opencode/agents/lean-formalization.md index e290655..9f7a5cb 100644 --- a/.opencode/agents/lean-formalization.md +++ b/.opencode/agents/lean-formalization.md @@ -8,6 +8,12 @@ Canonical workflow: skills/lean-formalization/SKILL.md ``` +Shared runtime support: + +```text +skills/lean-runtime/ +``` + Rules: - This is a coding-agent-first Lean skill. diff --git a/AGENTS.md b/AGENTS.md index 5862bb5..71b5b7d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,7 @@ Use `skills/lean-setup/SKILL.md` for setup-only tasks such as installing or verifying Lean 4, `elan`, `lake`, or a reusable mathlib workspace. Use the canonical shared Skill layer at `skills/lean-formalization/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. +Reusable scripts, examples, prompts, schemas, and references live in the non-user-facing support layer at `skills/lean-runtime/`; install it alongside the two public Skill entrypoints. Core rules: @@ -27,5 +28,5 @@ Core rules: Useful validation: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` diff --git a/CLAUDE.md b/CLAUDE.md index 570ee16..5d95f5a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,6 +12,12 @@ For Lean formalization or proof work in this repository, read and follow the sha skills/lean-formalization/SKILL.md ``` +Shared helper scripts, references, prompts, schemas, examples, and tests live in: + +```text +skills/lean-runtime/ +``` + Use Claude Code as the primary Lean coding agent. Official Numina is an optional deployable subagent backend; preserve that setup/call path but do not make it the default. Setup-only mode should create or verify the Lean/mathlib workspace without asking for a theorem target. diff --git a/GEMINI.md b/GEMINI.md index 427b59d..c0c5ac0 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -25,4 +25,4 @@ Setup-only readiness should focus on local Lean/mathlib state, and should mentio Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -The helper CLI under `skills/lean-formalization/scripts/` is optional tooling. It can report and configure the official Numina subagent runtime, but the agent should still validate final Lean patches locally. +The helper CLI under `skills/lean-runtime/scripts/` is optional tooling shared by the two public Skill entrypoints. It can report and configure the official Numina subagent runtime, but the agent should still validate final Lean patches locally. diff --git a/README.md b/README.md index 7533f25..a4b9e35 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ This repository provides two AI4Math Lean skills: - `lean-setup`: a setup-only entrypoint for Lean 4, `elan`, `lake`, and reusable mathlib workspace readiness. - `lean-formalization`: a coding-agent-first skill package for Lean 4 formalization, proof repair, and validation. +Both public skills share the bundled `skills/lean-runtime/` support layer for helper scripts, references, prompts, schemas, examples, and tests. Users invoke only the two public skills; installers should keep `lean-runtime` next to them. + `lean-formalization` is informed by publicly available Lean-specialist agent patterns from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. ## When To Use These Skills @@ -28,7 +30,7 @@ The agent should produce Lean patches, validation summaries, blocked-goal explan Copy this to your coding agent: ```text -Please install the `lean-setup` and `lean-formalization` skills from https://github.com/VeryMath/AI4Math-Lean-Agents.git. Read `.agent.md`, install the declared Skill entrypoints, verify that `$lean-setup` and `$lean-formalization` are discoverable, and tell me whether I need to restart the agent. +Please install the `lean-setup` and `lean-formalization` skills from https://github.com/VeryMath/AI4Math-Lean-Agents.git. Read `.agent.md`, install the declared Skill entrypoints together with their sibling `lean-runtime` support directory, verify that `$lean-setup` and `$lean-formalization` are discoverable, and tell me whether I need to restart the agent. ``` If you already have this skill repository locally, replace the repository URL @@ -95,7 +97,8 @@ Numina is optional. The public CLI does not expose a parallel `numina-*` workflo ├── .opencode/ # optional OpenCode agent └── skills/ ├── lean-setup/ # setup-only entrypoint - └── lean-formalization/ # proof/formalization implementation + ├── lean-formalization/ # proof/formalization entrypoint + └── lean-runtime/ # shared support layer, not a user-invoked skill ``` ## How To Interact @@ -117,28 +120,28 @@ claims. Run commands from the repository root: ```bash -python skills/lean-formalization/scripts/ai4m_lean.py env --cwd . -python skills/lean-formalization/scripts/ai4m_lean.py doctor --cwd . -python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace -python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run -python skills/lean-formalization/scripts/ai4m_lean.py check --cwd . --skip-build -python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +python skills/lean-runtime/scripts/ai4m_lean.py env --cwd . +python skills/lean-runtime/scripts/ai4m_lean.py doctor --cwd . +python skills/lean-runtime/scripts/ai4m_lean.py configure --cwd . --create-workspace +python skills/lean-runtime/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run +python skills/lean-runtime/scripts/ai4m_lean.py check --cwd . --skip-build +python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` The helper CLI is not the proof engine. The coding agent remains responsible for reading Lean errors, editing proofs, choosing proof strategy, and matching the user's language. -For the optional Numina path, read `skills/lean-formalization/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. +For the optional Numina path, read `skills/lean-runtime/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. ## Validate ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` For a full local Lean workspace check: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` ## Related Work and Public References diff --git a/README.zh-CN.md b/README.zh-CN.md index 74d0485..8114b6b 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -7,6 +7,8 @@ - `lean-setup`:用于 Lean 4、`elan`、`lake` 和可复用 mathlib workspace 的 setup-only 入口。 - `lean-formalization`:面向 coding agent 的 Lean 4 形式化、proof repair 和 validation skill package。 +两个公开 skill 共享随仓库提供的 `skills/lean-runtime/` 支持层,其中包含 helper scripts、references、prompts、schemas、examples 和 tests。用户只调用两个公开 skill;安装时应让 `lean-runtime` 保持在它们的 sibling 位置。 + `lean-formalization` 采用 coding-agent-first 定位,设计借鉴了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。 ## 适合什么任务 @@ -28,7 +30,7 @@ Agent 应产出 Lean patches、validation summaries、blocked-goal explanations 将以下安装请求提供给你的 coding agent: ```text -请帮我安装 `lean-setup` 和 `lean-formalization` skills,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git。请读取 `.agent.md`,安装其中声明的 Skill entrypoints,验证 `$lean-setup` 和 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 +请帮我安装 `lean-setup` 和 `lean-formalization` skills,链接是:https://github.com/VeryMath/AI4Math-Lean-Agents.git。请读取 `.agent.md`,安装其中声明的 Skill entrypoints,并同时安装它们 sibling 的 `lean-runtime` 支持目录;验证 `$lean-setup` 和 `$lean-formalization` 可用,并告诉我是否需要重启 agent。 ``` 如果你已经有本仓库的本地文件夹,可将链接替换为本地路径。coding agent 应负责 clone/link、配置、reload/restart 检查与验证。 @@ -106,7 +108,8 @@ Numina 是可选链路。公共 CLI 不提供并行的 `numina-*` workflow;`do ├── .opencode/ # optional OpenCode agent └── skills/ ├── lean-setup/ # setup-only entrypoint - └── lean-formalization/ # proof/formalization implementation + ├── lean-formalization/ # proof/formalization entrypoint + └── lean-runtime/ # shared support layer, not a user-invoked skill ``` ## 辅助命令 @@ -114,28 +117,28 @@ Numina 是可选链路。公共 CLI 不提供并行的 `numina-*` workflow;`do 在仓库根目录运行: ```bash -python skills/lean-formalization/scripts/ai4m_lean.py env --cwd . -python skills/lean-formalization/scripts/ai4m_lean.py doctor --cwd . -python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --create-workspace -python skills/lean-formalization/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run -python skills/lean-formalization/scripts/ai4m_lean.py check --cwd . --skip-build -python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +python skills/lean-runtime/scripts/ai4m_lean.py env --cwd . +python skills/lean-runtime/scripts/ai4m_lean.py doctor --cwd . +python skills/lean-runtime/scripts/ai4m_lean.py configure --cwd . --create-workspace +python skills/lean-runtime/scripts/ai4m_lean.py configure --cwd . --setup-numina --project-name myproofs --dry-run +python skills/lean-runtime/scripts/ai4m_lean.py check --cwd . --skip-build +python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` 辅助 CLI 不是 proof engine。coding agent 仍负责读取 Lean errors、编辑 proofs、选择 proof strategy,并匹配用户语言。 -可选 Numina 路径请读取 `skills/lean-formalization/references/numina_runtime.md`。setup 和 official runner calls 可能 clone repositories、安装工具或使用外部 model/API credentials,因此执行前应先说明。 +可选 Numina 路径请读取 `skills/lean-runtime/references/numina_runtime.md`。setup 和 official runner calls 可能 clone repositories、安装工具或使用外部 model/API credentials,因此执行前应先说明。 ## 维护者检查 ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` 完整本地 Lean workspace 检查: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --require-environment --include-workspace-build --run-tests ``` ## 相关工作与公开参考 diff --git a/SKILL.md b/SKILL.md index 3890219..b3dbf36 100644 --- a/SKILL.md +++ b/SKILL.md @@ -15,6 +15,12 @@ skills/lean-formalization/SKILL.md Read that concrete Skill before formalization or proof work. Keep platform adapters thin and improve the shared Skill layer first. +Reusable scripts, prompts, examples, references, schemas, and tests live in: + +```text +skills/lean-runtime/ +``` + For setup-only tasks such as installing Lean, checking `elan`/`lake`, or creating a reusable mathlib workspace, use: diff --git a/skills/lean-formalization/README.md b/skills/lean-formalization/README.md index 6784d26..4fac1d3 100644 --- a/skills/lean-formalization/README.md +++ b/skills/lean-formalization/README.md @@ -1,6 +1,6 @@ # Lean Formalization -`lean-formalization` is the concrete AI4Math skill package for Lean 4 +`lean-formalization` is the concrete AI4Math skill entrypoint for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, local validation, and optional official Numina runtime work. @@ -10,23 +10,19 @@ Start with [`SKILL.md`](SKILL.md). It defines the coding-agent-first workflow, the optional Numina boundary, safety rules, and the reference files to load for specific tasks. -## Package Layout +## Runtime Support -- `scripts/`: helper CLI commands for environment checks, validation, patch - review, Numina setup, and delivery verification. -- `references/`: task-specific guidance for direct Lean workflows, runtime - configuration, Numina, review, and failure reporting. -- `prompts/`: reusable task envelopes for formalization, proof repair, and - `sorry` completion. -- `config/` and `schemas/`: example configuration and validation schemas. -- `tests/`: package-level Python tests for the helper CLI and validation logic. +The reusable implementation lives in the sibling `../lean-runtime/` support +layer. It contains helper scripts, task-specific references, prompts, examples, +schemas, configuration templates, and tests. Keep `lean-runtime` installed next +to this entrypoint. ## Validation Run from the repository root: ```bash -PYTHONDONTWRITEBYTECODE=1 python skills/lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests +PYTHONDONTWRITEBYTECODE=1 python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests ``` ## Related Work and Public References diff --git a/skills/lean-formalization/SKILL.md b/skills/lean-formalization/SKILL.md index 02ab218..16c19e1 100644 --- a/skills/lean-formalization/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -9,6 +9,8 @@ Use this skill when the user wants a coding agent to do Lean 4 formalization, pr If the user only wants Lean 4, `elan`, `lake`, or a reusable mathlib workspace configured, use the sibling `../lean-setup/SKILL.md` entrypoint and do not ask for a theorem target. +Shared scripts, prompts, schemas, examples, and references live in the non-user-facing `../lean-runtime/` support layer. Treat `lean-setup` and `lean-formalization` as the two public entrypoints; do not ask users to invoke `lean-runtime` directly. + This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker. It reads and edits Lean files, runs Lean/Lake checks, diagnoses errors, preserves theorem statements, and iterates with the user. Default execution mode is coding-agent mode. Incorporate publicly documented Lean-specialist agent patterns into the default coding-agent workflow. Use systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents as related-work references for mechanisms such as project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Treat specialist-agent patterns as mechanisms, not mandatory external services. @@ -47,12 +49,12 @@ Do not remove the official Numina subagent path. Treat it as an optional backend ## Helper Toolbox -Use `python scripts/ai4m_lean.py ` when it saves effort or reduces risk: +Use `python ../lean-runtime/scripts/ai4m_lean.py ` when it saves effort or reduces risk: - `env` / `doctor`: inspect Lean workspace, local tool availability, and Numina subagent readiness. - `configure --create-workspace`: create or reuse the shared managed workspace. - `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`. -- `smoke-test`: run the bundled `examples/smoke/NuminaSmoke.lean` target in the shared workspace without external API calls. +- `smoke-test`: run the bundled `../lean-runtime/examples/smoke/NuminaSmoke.lean` target in the shared workspace without external API calls. - `check`: run a structured Lean/Lake validation. - `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. - `minimize-failure`: extract a compact failing Lean fragment. @@ -63,7 +65,7 @@ All helper commands emit machine-readable JSON on stdout. Human-readable diagnos ## Numina Runtime -When using the official Numina runtime, follow `references/numina_runtime.md`. For auth/proxy/MCP/failure triage, follow `references/numina_subagent_troubleshooting.md`. Proof strategy is a human-in-the-loop process with the user, the coding agent, local Lean checks, and, when approved, the official Numina runner as an optional subagent backend. +When using the official Numina runtime, follow `../lean-runtime/references/numina_runtime.md`. For auth/proxy/MCP/failure triage, follow `../lean-runtime/references/numina_subagent_troubleshooting.md`. Proof strategy is a human-in-the-loop process with the user, the coding agent, local Lean checks, and, when approved, the official Numina runner as an optional subagent backend. ## Safety Rules @@ -79,12 +81,12 @@ When using the official Numina runtime, follow `references/numina_runtime.md`. F ## References -- Read `references/direct_lean_workflow.md` for the default coding-agent proof/repair/formalization loop. -- Read `references/specialist_agent_patterns.md` when adapting ideas from Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP, or other Lean-specialist agents. -- Read `references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. -- Read `references/numina_runtime.md` when the user wants the official Numina deployment/call path. -- Read `references/numina_subagent_troubleshooting.md` when Numina auth, proxy, MCP, or runner failures appear. -- Read `references/interactive_orchestration.md` when guiding user intake and task decomposition. -- Read `references/review_checklist.md` before accepting a Lean patch. -- Read `references/failure_taxonomy.md` when reporting a blocked proof. -- Read `references/numina_reverse_analysis.md` when explaining which Numina mechanisms are incorporated locally and which are delegated to the optional official runtime. +- Read `../lean-runtime/references/direct_lean_workflow.md` for the default coding-agent proof/repair/formalization loop. +- Read `../lean-runtime/references/specialist_agent_patterns.md` when adapting ideas from Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP, or other Lean-specialist agents. +- Read `../lean-runtime/references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. +- Read `../lean-runtime/references/numina_runtime.md` when the user wants the official Numina deployment/call path. +- Read `../lean-runtime/references/numina_subagent_troubleshooting.md` when Numina auth, proxy, MCP, or runner failures appear. +- Read `../lean-runtime/references/interactive_orchestration.md` when guiding user intake and task decomposition. +- Read `../lean-runtime/references/review_checklist.md` before accepting a Lean patch. +- Read `../lean-runtime/references/failure_taxonomy.md` when reporting a blocked proof. +- Read `../lean-runtime/references/numina_reverse_analysis.md` when explaining which Numina mechanisms are incorporated locally and which are delegated to the optional official runtime. diff --git a/skills/lean-formalization/config/env.example b/skills/lean-runtime/config/env.example similarity index 100% rename from skills/lean-formalization/config/env.example rename to skills/lean-runtime/config/env.example diff --git a/skills/lean-formalization/config/lean_agent.example.toml b/skills/lean-runtime/config/lean_agent.example.toml similarity index 100% rename from skills/lean-formalization/config/lean_agent.example.toml rename to skills/lean-runtime/config/lean_agent.example.toml diff --git a/skills/lean-formalization/config/numina_runtime.example.toml b/skills/lean-runtime/config/numina_runtime.example.toml similarity index 100% rename from skills/lean-formalization/config/numina_runtime.example.toml rename to skills/lean-runtime/config/numina_runtime.example.toml diff --git a/skills/lean-formalization/examples/smoke/NuminaSmoke.lean b/skills/lean-runtime/examples/smoke/NuminaSmoke.lean similarity index 100% rename from skills/lean-formalization/examples/smoke/NuminaSmoke.lean rename to skills/lean-runtime/examples/smoke/NuminaSmoke.lean diff --git a/skills/lean-formalization/prompts/complete_sorries.md b/skills/lean-runtime/prompts/complete_sorries.md similarity index 100% rename from skills/lean-formalization/prompts/complete_sorries.md rename to skills/lean-runtime/prompts/complete_sorries.md diff --git a/skills/lean-formalization/prompts/formalize_statement.md b/skills/lean-runtime/prompts/formalize_statement.md similarity index 100% rename from skills/lean-formalization/prompts/formalize_statement.md rename to skills/lean-runtime/prompts/formalize_statement.md diff --git a/skills/lean-formalization/prompts/prove_theorem.md b/skills/lean-runtime/prompts/prove_theorem.md similarity index 100% rename from skills/lean-formalization/prompts/prove_theorem.md rename to skills/lean-runtime/prompts/prove_theorem.md diff --git a/skills/lean-formalization/prompts/repair_lean_file.md b/skills/lean-runtime/prompts/repair_lean_file.md similarity index 100% rename from skills/lean-formalization/prompts/repair_lean_file.md rename to skills/lean-runtime/prompts/repair_lean_file.md diff --git a/skills/lean-formalization/references/direct_lean_workflow.md b/skills/lean-runtime/references/direct_lean_workflow.md similarity index 100% rename from skills/lean-formalization/references/direct_lean_workflow.md rename to skills/lean-runtime/references/direct_lean_workflow.md diff --git a/skills/lean-formalization/references/failure_taxonomy.md b/skills/lean-runtime/references/failure_taxonomy.md similarity index 100% rename from skills/lean-formalization/references/failure_taxonomy.md rename to skills/lean-runtime/references/failure_taxonomy.md diff --git a/skills/lean-formalization/references/interactive_orchestration.md b/skills/lean-runtime/references/interactive_orchestration.md similarity index 100% rename from skills/lean-formalization/references/interactive_orchestration.md rename to skills/lean-runtime/references/interactive_orchestration.md diff --git a/skills/lean-formalization/references/lean_runtime_configuration.md b/skills/lean-runtime/references/lean_runtime_configuration.md similarity index 89% rename from skills/lean-formalization/references/lean_runtime_configuration.md rename to skills/lean-runtime/references/lean_runtime_configuration.md index f4cb8e3..f0c080f 100644 --- a/skills/lean-formalization/references/lean_runtime_configuration.md +++ b/skills/lean-runtime/references/lean_runtime_configuration.md @@ -20,8 +20,8 @@ Repository-local machine settings still live under `/.ai4math/` and should Use: ```bash -python scripts/ai4m_lean.py doctor --cwd . -python scripts/ai4m_lean.py env --cwd . +python skills/lean-runtime/scripts/ai4m_lean.py doctor --cwd . +python skills/lean-runtime/scripts/ai4m_lean.py env --cwd . ``` Required default workflow tools are `git`, `python3`, `elan`, `lean`, and `lake`. Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Official Numina subagent calls need a working Claude CLI/auth path and may need additional API keys for search/tool skills. @@ -31,7 +31,7 @@ Required default workflow tools are `git`, `python3`, `elan`, `lean`, and `lake` For standalone tasks, prefer `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`. Create it once with: ```bash -python scripts/ai4m_lean.py configure --cwd . --create-workspace --toolchain leanprover/lean4:v4.28.0 +python skills/lean-runtime/scripts/ai4m_lean.py configure --cwd . --create-workspace --toolchain leanprover/lean4:v4.28.0 ``` Equivalent Lake commands: diff --git a/skills/lean-formalization/references/numina_reverse_analysis.md b/skills/lean-runtime/references/numina_reverse_analysis.md similarity index 100% rename from skills/lean-formalization/references/numina_reverse_analysis.md rename to skills/lean-runtime/references/numina_reverse_analysis.md diff --git a/skills/lean-formalization/references/numina_runtime.md b/skills/lean-runtime/references/numina_runtime.md similarity index 100% rename from skills/lean-formalization/references/numina_runtime.md rename to skills/lean-runtime/references/numina_runtime.md diff --git a/skills/lean-formalization/references/numina_subagent_troubleshooting.md b/skills/lean-runtime/references/numina_subagent_troubleshooting.md similarity index 100% rename from skills/lean-formalization/references/numina_subagent_troubleshooting.md rename to skills/lean-runtime/references/numina_subagent_troubleshooting.md diff --git a/skills/lean-formalization/references/review_checklist.md b/skills/lean-runtime/references/review_checklist.md similarity index 100% rename from skills/lean-formalization/references/review_checklist.md rename to skills/lean-runtime/references/review_checklist.md diff --git a/skills/lean-formalization/references/specialist_agent_patterns.md b/skills/lean-runtime/references/specialist_agent_patterns.md similarity index 100% rename from skills/lean-formalization/references/specialist_agent_patterns.md rename to skills/lean-runtime/references/specialist_agent_patterns.md diff --git a/skills/lean-formalization/schemas/config.schema.json b/skills/lean-runtime/schemas/config.schema.json similarity index 100% rename from skills/lean-formalization/schemas/config.schema.json rename to skills/lean-runtime/schemas/config.schema.json diff --git a/skills/lean-formalization/schemas/result.schema.json b/skills/lean-runtime/schemas/result.schema.json similarity index 100% rename from skills/lean-formalization/schemas/result.schema.json rename to skills/lean-runtime/schemas/result.schema.json diff --git a/skills/lean-formalization/schemas/task.schema.json b/skills/lean-runtime/schemas/task.schema.json similarity index 100% rename from skills/lean-formalization/schemas/task.schema.json rename to skills/lean-runtime/schemas/task.schema.json diff --git a/skills/lean-formalization/scripts/ai4m_lean.py b/skills/lean-runtime/scripts/ai4m_lean.py similarity index 100% rename from skills/lean-formalization/scripts/ai4m_lean.py rename to skills/lean-runtime/scripts/ai4m_lean.py diff --git a/skills/lean-formalization/scripts/check_lean_project.py b/skills/lean-runtime/scripts/check_lean_project.py similarity index 100% rename from skills/lean-formalization/scripts/check_lean_project.py rename to skills/lean-runtime/scripts/check_lean_project.py diff --git a/skills/lean-formalization/scripts/common.py b/skills/lean-runtime/scripts/common.py similarity index 100% rename from skills/lean-formalization/scripts/common.py rename to skills/lean-runtime/scripts/common.py diff --git a/skills/lean-formalization/scripts/configure_lean.py b/skills/lean-runtime/scripts/configure_lean.py similarity index 100% rename from skills/lean-formalization/scripts/configure_lean.py rename to skills/lean-runtime/scripts/configure_lean.py diff --git a/skills/lean-formalization/scripts/detect_sorry.py b/skills/lean-runtime/scripts/detect_sorry.py similarity index 100% rename from skills/lean-formalization/scripts/detect_sorry.py rename to skills/lean-runtime/scripts/detect_sorry.py diff --git a/skills/lean-formalization/scripts/direct_task.py b/skills/lean-runtime/scripts/direct_task.py similarity index 100% rename from skills/lean-formalization/scripts/direct_task.py rename to skills/lean-runtime/scripts/direct_task.py diff --git a/skills/lean-formalization/scripts/extract_minimal_failure.py b/skills/lean-runtime/scripts/extract_minimal_failure.py similarity index 100% rename from skills/lean-formalization/scripts/extract_minimal_failure.py rename to skills/lean-runtime/scripts/extract_minimal_failure.py diff --git a/skills/lean-formalization/scripts/numina_runtime.py b/skills/lean-runtime/scripts/numina_runtime.py similarity index 100% rename from skills/lean-formalization/scripts/numina_runtime.py rename to skills/lean-runtime/scripts/numina_runtime.py diff --git a/skills/lean-formalization/scripts/smoke_test.py b/skills/lean-runtime/scripts/smoke_test.py similarity index 100% rename from skills/lean-formalization/scripts/smoke_test.py rename to skills/lean-runtime/scripts/smoke_test.py diff --git a/skills/lean-formalization/scripts/tool_status.py b/skills/lean-runtime/scripts/tool_status.py similarity index 100% rename from skills/lean-formalization/scripts/tool_status.py rename to skills/lean-runtime/scripts/tool_status.py diff --git a/skills/lean-formalization/scripts/validate_patch.py b/skills/lean-runtime/scripts/validate_patch.py similarity index 100% rename from skills/lean-formalization/scripts/validate_patch.py rename to skills/lean-runtime/scripts/validate_patch.py diff --git a/skills/lean-formalization/scripts/verify_delivery.py b/skills/lean-runtime/scripts/verify_delivery.py similarity index 90% rename from skills/lean-formalization/scripts/verify_delivery.py rename to skills/lean-runtime/scripts/verify_delivery.py index a833944..af03fa6 100644 --- a/skills/lean-formalization/scripts/verify_delivery.py +++ b/skills/lean-runtime/scripts/verify_delivery.py @@ -17,11 +17,15 @@ from validate_patch import review_files -SKILL_ROOT = Path(__file__).resolve().parents[1] -SKILLS_ROOT = SKILL_ROOT.parent -REQUIRED_FILES = [ +RUNTIME_ROOT = Path(__file__).resolve().parents[1] +SKILLS_ROOT = RUNTIME_ROOT.parent +FORMALIZATION_ROOT = SKILLS_ROOT / "lean-formalization" +SETUP_ROOT = SKILLS_ROOT / "lean-setup" +REQUIRED_FORMALIZATION_FILES = [ "SKILL.md", "agents/openai.yaml", +] +REQUIRED_RUNTIME_FILES = [ "config/lean_agent.example.toml", "config/numina_runtime.example.toml", "examples/smoke/NuminaSmoke.lean", @@ -78,10 +82,10 @@ def _load_schema(path: Path) -> dict[str, Any]: def _package_hygiene() -> dict[str, Any]: - package_roots = [SKILL_ROOT] - setup_root = SKILLS_ROOT / "lean-setup" - if setup_root.exists(): - package_roots.append(setup_root) + package_roots = [RUNTIME_ROOT] + for root in (FORMALIZATION_ROOT, SETUP_ROOT): + if root.exists(): + package_roots.append(root) generated = [ str(path.relative_to(SKILLS_ROOT)) for root in package_roots @@ -115,8 +119,8 @@ def _package_hygiene() -> dict[str, Any]: def _guidance_first_check() -> dict[str, Any]: - text = (SKILL_ROOT / "SKILL.md").read_text(encoding="utf-8", errors="replace") - orchestration = (SKILL_ROOT / "references" / "interactive_orchestration.md").read_text(encoding="utf-8", errors="replace") + text = (FORMALIZATION_ROOT / "SKILL.md").read_text(encoding="utf-8", errors="replace") + orchestration = (RUNTIME_ROOT / "references" / "interactive_orchestration.md").read_text(encoding="utf-8", errors="replace") required_phrases = [ "## Agent Playbook", "## Helper Toolbox", @@ -160,7 +164,7 @@ def _guidance_first_check() -> dict[str, Any]: "A good opening ends with one decision question, not a checklist.", ] orchestration_missing = [phrase for phrase in orchestration_required if phrase not in orchestration] - openai_yaml = (SKILL_ROOT / "agents" / "openai.yaml").read_text(encoding="utf-8", errors="replace") + openai_yaml = (FORMALIZATION_ROOT / "agents" / "openai.yaml").read_text(encoding="utf-8", errors="replace") openai_required = [ "请用中文开始", "如果用户明确使用其他语言", @@ -209,15 +213,14 @@ def _root_discovery_boundary_check() -> dict[str, Any]: def _lean_setup_entrypoint_check() -> dict[str, Any]: - setup_root = SKILLS_ROOT / "lean-setup" - skill_path = setup_root / "SKILL.md" - openai_path = setup_root / "agents" / "openai.yaml" - helper_script = SKILL_ROOT / "scripts" / "ai4m_lean.py" + skill_path = SETUP_ROOT / "SKILL.md" + openai_path = SETUP_ROOT / "agents" / "openai.yaml" + helper_script = RUNTIME_ROOT / "scripts" / "ai4m_lean.py" required_files = [skill_path, openai_path] if not all(path.exists() for path in required_files): return { "ok": False, - "setup_root": str(setup_root), + "setup_root": str(SETUP_ROOT), "helper_script": str(helper_script), "helper_script_exists": helper_script.exists(), "missing_files": [str(path) for path in required_files if not path.exists()], @@ -230,8 +233,8 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: required_phrases = [ "Use this setup-only entrypoint", "Do not ask for a theorem target in setup-only mode.", - "The canonical implementation lives in `../lean-formalization/`.", - "../lean-formalization/scripts/ai4m_lean.py", + "The shared implementation lives in `../lean-runtime/`.", + "../lean-runtime/scripts/ai4m_lean.py", "Install Lean through the official `elan` channel", "When creating an isolated test directory or workspace", "suggest a safe default name", @@ -245,7 +248,7 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: repo_root_command_hits = [phrase for phrase in repo_root_commands if phrase in text] openai_required = [ "不要向用户索要 theorem target", - "所有实现应复用 lean-formalization", + "所有实现应复用 lean-runtime", "默认 Lean/mathlib 环境配置不需要 API key", "应交接到 lean-formalization", ] @@ -256,7 +259,7 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: and all(phrase in text for phrase in required_phrases) and all(phrase in openai_yaml for phrase in openai_required) ), - "setup_root": str(setup_root), + "setup_root": str(SETUP_ROOT), "helper_script": str(helper_script), "helper_script_exists": helper_script.exists(), "missing_phrases": [phrase for phrase in required_phrases if phrase not in text], @@ -272,18 +275,24 @@ def verify( run_tests: bool = False, ) -> dict[str, Any]: cwd_path = Path(cwd).resolve() - files = [{"path": item, "exists": (SKILL_ROOT / item).exists()} for item in REQUIRED_FILES] + files = [ + {"path": f"lean-formalization/{item}", "exists": (FORMALIZATION_ROOT / item).exists()} + for item in REQUIRED_FORMALIZATION_FILES + ] + [ + {"path": f"lean-runtime/{item}", "exists": (RUNTIME_ROOT / item).exists()} + for item in REQUIRED_RUNTIME_FILES + ] commands = _parser_commands() schemas = [] for name in ("task.schema.json", "result.schema.json", "config.schema.json"): - path = SKILL_ROOT / "schemas" / name + path = RUNTIME_ROOT / "schemas" / name try: _load_schema(path) schemas.append({"path": f"schemas/{name}", "ok": True}) except Exception as exc: # noqa: BLE001 - report schema parse failure in JSON schemas.append({"path": f"schemas/{name}", "ok": False, "error": str(exc)}) - fixtures = SKILL_ROOT / "tests" / "fixtures" + fixtures = RUNTIME_ROOT / "tests" / "fixtures" with tempfile.TemporaryDirectory() as tmp: dry_root = Path(tmp) dry_target = dry_root / "Failure.lean" @@ -311,7 +320,7 @@ def verify( tests = None if run_tests: - tests = run_command([sys.executable, "-m", "unittest", "discover", "-s", str(SKILL_ROOT / "tests")], cwd=SKILL_ROOT, timeout=300) + tests = run_command([sys.executable, "-m", "unittest", "discover", "-s", str(RUNTIME_ROOT / "tests")], cwd=RUNTIME_ROOT, timeout=300) hygiene = _package_hygiene() guidance_first = _guidance_first_check() @@ -345,7 +354,9 @@ def verify( "ok": ok, "status": "delivery_ready" if ok else "delivery_blocked", "cwd": str(cwd_path), - "skill_root": str(SKILL_ROOT), + "runtime_root": str(RUNTIME_ROOT), + "formalization_root": str(FORMALIZATION_ROOT), + "setup_root": str(SETUP_ROOT), "checks": checks, "files": files, "commands": { diff --git a/skills/lean-formalization/tests/fixtures/after_bad.lean b/skills/lean-runtime/tests/fixtures/after_bad.lean similarity index 100% rename from skills/lean-formalization/tests/fixtures/after_bad.lean rename to skills/lean-runtime/tests/fixtures/after_bad.lean diff --git a/skills/lean-formalization/tests/fixtures/after_statement_changed.lean b/skills/lean-runtime/tests/fixtures/after_statement_changed.lean similarity index 100% rename from skills/lean-formalization/tests/fixtures/after_statement_changed.lean rename to skills/lean-runtime/tests/fixtures/after_statement_changed.lean diff --git a/skills/lean-formalization/tests/fixtures/before.lean b/skills/lean-runtime/tests/fixtures/before.lean similarity index 100% rename from skills/lean-formalization/tests/fixtures/before.lean rename to skills/lean-runtime/tests/fixtures/before.lean diff --git a/skills/lean-formalization/tests/fixtures/failure.lean b/skills/lean-runtime/tests/fixtures/failure.lean similarity index 100% rename from skills/lean-formalization/tests/fixtures/failure.lean rename to skills/lean-runtime/tests/fixtures/failure.lean diff --git a/skills/lean-formalization/tests/test_check_lean_project.py b/skills/lean-runtime/tests/test_check_lean_project.py similarity index 100% rename from skills/lean-formalization/tests/test_check_lean_project.py rename to skills/lean-runtime/tests/test_check_lean_project.py diff --git a/skills/lean-formalization/tests/test_cli.py b/skills/lean-runtime/tests/test_cli.py similarity index 92% rename from skills/lean-formalization/tests/test_cli.py rename to skills/lean-runtime/tests/test_cli.py index 0780675..8ead830 100644 --- a/skills/lean-formalization/tests/test_cli.py +++ b/skills/lean-runtime/tests/test_cli.py @@ -9,6 +9,7 @@ from pathlib import Path SKILL_ROOT = Path(__file__).resolve().parents[1] +SKILLS_ROOT = SKILL_ROOT.parent sys.path.insert(0, str(SKILL_ROOT / "scripts")) from ai4m_lean import EXIT_LEAN_FAILED, _exit_code # noqa: E402 @@ -162,6 +163,17 @@ def test_lean_setup_entrypoint_uses_sibling_helper_layout(self) -> None: self.assertTrue(setup["helper_script_exists"], setup) self.assertFalse(setup["repo_root_command_hits"], setup) + def test_two_public_skills_share_hidden_runtime_layer(self) -> None: + runtime_root = SKILLS_ROOT / "lean-runtime" + runtime_cli = runtime_root / "scripts" / "ai4m_lean.py" + setup_text = (SKILLS_ROOT / "lean-setup" / "SKILL.md").read_text(encoding="utf-8") + formalization_text = (SKILLS_ROOT / "lean-formalization" / "SKILL.md").read_text(encoding="utf-8") + + self.assertTrue(runtime_cli.exists()) + self.assertIn("../lean-runtime/scripts/ai4m_lean.py", setup_text) + self.assertIn("../lean-runtime/scripts/ai4m_lean.py", formalization_text) + self.assertNotIn("../lean-formalization/scripts/ai4m_lean.py", setup_text) + def test_lean_setup_offers_default_names_for_isolated_setup(self) -> None: text = (SKILL_ROOT.parent / "lean-setup" / "SKILL.md").read_text(encoding="utf-8") self.assertIn("When creating an isolated test directory or workspace", text) diff --git a/skills/lean-formalization/tests/test_common_config.py b/skills/lean-runtime/tests/test_common_config.py similarity index 100% rename from skills/lean-formalization/tests/test_common_config.py rename to skills/lean-runtime/tests/test_common_config.py diff --git a/skills/lean-formalization/tests/test_configure_lean.py b/skills/lean-runtime/tests/test_configure_lean.py similarity index 100% rename from skills/lean-formalization/tests/test_configure_lean.py rename to skills/lean-runtime/tests/test_configure_lean.py diff --git a/skills/lean-formalization/tests/test_detect_sorry.py b/skills/lean-runtime/tests/test_detect_sorry.py similarity index 100% rename from skills/lean-formalization/tests/test_detect_sorry.py rename to skills/lean-runtime/tests/test_detect_sorry.py diff --git a/skills/lean-formalization/tests/test_direct_task.py b/skills/lean-runtime/tests/test_direct_task.py similarity index 100% rename from skills/lean-formalization/tests/test_direct_task.py rename to skills/lean-runtime/tests/test_direct_task.py diff --git a/skills/lean-formalization/tests/test_numina_runtime.py b/skills/lean-runtime/tests/test_numina_runtime.py similarity index 100% rename from skills/lean-formalization/tests/test_numina_runtime.py rename to skills/lean-runtime/tests/test_numina_runtime.py diff --git a/skills/lean-formalization/tests/test_validate_patch.py b/skills/lean-runtime/tests/test_validate_patch.py similarity index 100% rename from skills/lean-formalization/tests/test_validate_patch.py rename to skills/lean-runtime/tests/test_validate_patch.py diff --git a/skills/lean-setup/SKILL.md b/skills/lean-setup/SKILL.md index 26a7c97..24c0e3a 100644 --- a/skills/lean-setup/SKILL.md +++ b/skills/lean-setup/SKILL.md @@ -7,7 +7,7 @@ description: Use when a coding agent needs to install or verify Lean 4, elan, la Use this setup-only entrypoint when the user only wants a Lean 4 environment, `elan`/`lake` readiness, or a reusable mathlib workspace. Do not ask for a theorem target in setup-only mode. -The canonical implementation lives in `../lean-formalization/`. This skill must reuse the same helper CLI, configuration rules, and runtime references rather than duplicating setup logic. +The shared implementation lives in `../lean-runtime/`. This skill must reuse the same helper CLI, configuration rules, and runtime references rather than duplicating setup logic or depending on the formalization entrypoint. ## Setup-Only Flow @@ -24,13 +24,13 @@ The canonical implementation lives in `../lean-formalization/`. This skill must ## Commands -Resolve the helper from the sibling skill path `../lean-formalization/scripts/ai4m_lean.py`, then run it with `--cwd `. In a source checkout this is the same helper under `skills/lean-formalization/scripts/ai4m_lean.py`. +Resolve the helper from the shared runtime path `../lean-runtime/scripts/ai4m_lean.py`, then run it with `--cwd `. In a source checkout this is the same helper under `skills/lean-runtime/scripts/ai4m_lean.py`. ```bash -python ../lean-formalization/scripts/ai4m_lean.py doctor --cwd -python ../lean-formalization/scripts/ai4m_lean.py env --cwd -python ../lean-formalization/scripts/ai4m_lean.py configure --cwd --create-workspace -python ../lean-formalization/scripts/ai4m_lean.py smoke-test --cwd +python ../lean-runtime/scripts/ai4m_lean.py doctor --cwd +python ../lean-runtime/scripts/ai4m_lean.py env --cwd +python ../lean-runtime/scripts/ai4m_lean.py configure --cwd --create-workspace +python ../lean-runtime/scripts/ai4m_lean.py smoke-test --cwd ``` Use `--dry-run` before setup when the user wants to review commands. @@ -45,6 +45,6 @@ Use `--dry-run` before setup when the user wants to review commands. ## References -- Read `../lean-formalization/references/lean_runtime_configuration.md` for shared workspace layout, local configuration, and version policy. -- Read `../lean-formalization/references/numina_runtime.md` only when the user asks for optional official Numina setup. -- Use `../lean-formalization/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests` for package validation. +- Read `../lean-runtime/references/lean_runtime_configuration.md` for shared workspace layout, local configuration, and version policy. +- Read `../lean-runtime/references/numina_runtime.md` only when the user asks for optional official Numina setup. +- Use `../lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --run-tests` for package validation. diff --git a/skills/lean-setup/agents/openai.yaml b/skills/lean-setup/agents/openai.yaml index 99aabc3..f0a55b5 100644 --- a/skills/lean-setup/agents/openai.yaml +++ b/skills/lean-setup/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: Lean Setup short_description: Lean 4, elan, lake, and reusable mathlib workspace setup for coding agents. -default_prompt: 请默认使用中文,并主动完成 Lean 环境配置引导;仅当用户明确使用其他语言时切换。该入口仅用于 setup-only 任务:检查或安装 Lean/elan/lake,创建或复用带 mathlib 的共享工作区,运行 smoke-test,并报告 workspace 路径、toolchain、mathlib revision、验证结果与剩余动作。不要向用户索要 theorem target。所有实现应复用 lean-formalization 的 helper CLI 与 runtime references,不复制第二套配置逻辑。默认 Lean/mathlib 环境配置不需要 API key;只有在用户明确要求 optional official Numina backend 时,才说明凭据需求并请求批准。配置完成后,如用户要进行形式化、proof repair、sorry completion 或 Numina proof search,应交接到 lean-formalization。 +default_prompt: 请默认使用中文,并主动完成 Lean 环境配置引导;仅当用户明确使用其他语言时切换。该入口仅用于 setup-only 任务:检查或安装 Lean/elan/lake,创建或复用带 mathlib 的共享工作区,运行 smoke-test,并报告 workspace 路径、toolchain、mathlib revision、验证结果与剩余动作。不要向用户索要 theorem target。所有实现应复用 lean-runtime 的 helper CLI 与 runtime references,不复制第二套配置逻辑,也不要把 lean-formalization 当作 setup 的实现依赖。默认 Lean/mathlib 环境配置不需要 API key;只有在用户明确要求 optional official Numina backend 时,才说明凭据需求并请求批准。配置完成后,如用户要进行形式化、proof repair、sorry completion 或 Numina proof search,应交接到 lean-formalization。 From fd6b05ccc6c9c98d3769912d912cc78315f4f09e Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 17:58:02 +0800 Subject: [PATCH 36/37] Guide users after Lean setup --- skills/lean-runtime/scripts/verify_delivery.py | 8 ++++++++ skills/lean-runtime/tests/test_cli.py | 9 +++++++++ skills/lean-setup/SKILL.md | 15 ++++++++++++++- skills/lean-setup/agents/openai.yaml | 2 +- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/skills/lean-runtime/scripts/verify_delivery.py b/skills/lean-runtime/scripts/verify_delivery.py index af03fa6..cf9d624 100644 --- a/skills/lean-runtime/scripts/verify_delivery.py +++ b/skills/lean-runtime/scripts/verify_delivery.py @@ -239,6 +239,12 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: "When creating an isolated test directory or workspace", "suggest a safe default name", "use the default if the user has no naming preference", + "After successful setup or smoke-test validation", + "Offer a short next-step menu", + "inspect an existing Lean/Lake project", + "repair a Lean file or complete `sorry`", + "formalize a natural-language or LaTeX theorem", + "mention optional Numina only when the user explicitly asks", "Do not require API keys for Lean/mathlib workspace setup.", "hand off to `lean-formalization`", ] @@ -248,8 +254,10 @@ def _lean_setup_entrypoint_check() -> dict[str, Any]: repo_root_command_hits = [phrase for phrase in repo_root_commands if phrase in text] openai_required = [ "不要向用户索要 theorem target", + "setup 完成后主动给出下一步菜单", "所有实现应复用 lean-runtime", "默认 Lean/mathlib 环境配置不需要 API key", + "不要把 Numina 放进默认下一步", "应交接到 lean-formalization", ] return { diff --git a/skills/lean-runtime/tests/test_cli.py b/skills/lean-runtime/tests/test_cli.py index 8ead830..79e6636 100644 --- a/skills/lean-runtime/tests/test_cli.py +++ b/skills/lean-runtime/tests/test_cli.py @@ -180,6 +180,15 @@ def test_lean_setup_offers_default_names_for_isolated_setup(self) -> None: self.assertIn("suggest a safe default name", text) self.assertIn("use the default if the user has no naming preference", text) + def test_lean_setup_guides_next_step_after_successful_setup(self) -> None: + text = (SKILL_ROOT.parent / "lean-setup" / "SKILL.md").read_text(encoding="utf-8") + self.assertIn("After successful setup or smoke-test validation", text) + self.assertIn("Offer a short next-step menu", text) + self.assertIn("inspect an existing Lean/Lake project", text) + self.assertIn("repair a Lean file or complete `sorry`", text) + self.assertIn("formalize a natural-language or LaTeX theorem", text) + self.assertIn("mention optional Numina only when the user explicitly asks", text) + def test_package_hygiene_scans_lean_setup_entrypoint(self) -> None: generated = SKILL_ROOT.parent / "lean-setup" / "__pycache__" / "sentinel.pyc" generated.parent.mkdir(exist_ok=True) diff --git a/skills/lean-setup/SKILL.md b/skills/lean-setup/SKILL.md index 24c0e3a..e2ce7eb 100644 --- a/skills/lean-setup/SKILL.md +++ b/skills/lean-setup/SKILL.md @@ -20,7 +20,20 @@ The shared implementation lives in `../lean-runtime/`. This skill must reuse the 7. Create the workspace only after explaining that Lean/mathlib artifacts may be downloaded or built. 8. Run the bundled smoke test after setup. 9. Report the installed tools, workspace path, Lean toolchain, mathlib revision when available, smoke-test result, and any remaining action. -10. If the user next wants formalization, proof repair, theorem transcription, `sorry` completion, patch review, or Numina proof search, hand off to `lean-formalization`. +10. After successful setup or smoke-test validation, do not end passively. Offer a short next-step menu and recommend one default next action. +11. If the user next wants formalization, proof repair, theorem transcription, `sorry` completion, patch review, or Numina proof search, hand off to `lean-formalization`. + +## Post-Setup Guidance + +Offer a short next-step menu after setup succeeds: + +- inspect an existing Lean/Lake project; +- run or explain the built-in smoke theorem result; +- repair a Lean file or complete `sorry`; +- formalize a natural-language or LaTeX theorem; +- continue setup-only validation if the user only wants environment readiness. + +As a rule, mention optional Numina only when the user explicitly asks for the official Lean Agent, batch proof search, or an external subagent backend; do not make Numina or API keys part of the default next step. ## Commands diff --git a/skills/lean-setup/agents/openai.yaml b/skills/lean-setup/agents/openai.yaml index f0a55b5..81dee2e 100644 --- a/skills/lean-setup/agents/openai.yaml +++ b/skills/lean-setup/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: Lean Setup short_description: Lean 4, elan, lake, and reusable mathlib workspace setup for coding agents. -default_prompt: 请默认使用中文,并主动完成 Lean 环境配置引导;仅当用户明确使用其他语言时切换。该入口仅用于 setup-only 任务:检查或安装 Lean/elan/lake,创建或复用带 mathlib 的共享工作区,运行 smoke-test,并报告 workspace 路径、toolchain、mathlib revision、验证结果与剩余动作。不要向用户索要 theorem target。所有实现应复用 lean-runtime 的 helper CLI 与 runtime references,不复制第二套配置逻辑,也不要把 lean-formalization 当作 setup 的实现依赖。默认 Lean/mathlib 环境配置不需要 API key;只有在用户明确要求 optional official Numina backend 时,才说明凭据需求并请求批准。配置完成后,如用户要进行形式化、proof repair、sorry completion 或 Numina proof search,应交接到 lean-formalization。 +default_prompt: 请默认使用中文,并主动完成 Lean 环境配置引导;仅当用户明确使用其他语言时切换。该入口仅用于 setup-only 任务:检查或安装 Lean/elan/lake,创建或复用带 mathlib 的共享工作区,运行 smoke-test,并报告 workspace 路径、toolchain、mathlib revision、验证结果与剩余动作。不要向用户索要 theorem target。setup 完成后主动给出下一步菜单,例如检查 Lean/Lake 项目、运行或解释 smoke theorem、修 Lean 文件或补 sorry、形式化自然语言/LaTeX 命题,或继续 setup-only readiness;推荐一个默认下一步。所有实现应复用 lean-runtime 的 helper CLI 与 runtime references,不复制第二套配置逻辑,也不要把 lean-formalization 当作 setup 的实现依赖。默认 Lean/mathlib 环境配置不需要 API key;只有在用户明确要求 optional official Numina backend 时,才说明凭据需求并请求批准,不要把 Numina 放进默认下一步。配置完成后,如用户要进行形式化、proof repair、sorry completion 或 Numina proof search,应交接到 lean-formalization。 From 3fcd5607f2e632b0f9da54e35cdec650eb8e631d Mon Sep 17 00:00:00 2001 From: conanxu <1845830029@qq.com> Date: Fri, 26 Jun 2026 18:27:30 +0800 Subject: [PATCH 37/37] Generalize optional Lean backend adapters --- .cursor/rules/lean-formalization.mdc | 4 +-- AGENTS.md | 6 ++-- CLAUDE.md | 6 ++-- GEMINI.md | 6 ++-- README.md | 18 ++++++----- README.zh-CN.md | 16 ++++++---- SKILL.md | 4 +-- skills/lean-formalization/README.md | 7 +++-- skills/lean-formalization/SKILL.md | 27 ++++++++-------- skills/lean-formalization/agents/openai.yaml | 4 +-- .../references/backend_adapter_checklist.md | 31 +++++++++++++++++++ .../references/direct_lean_workflow.md | 4 +-- .../references/interactive_orchestration.md | 28 +++++++++-------- .../references/lean_runtime_configuration.md | 6 ++-- .../references/numina_reverse_analysis.md | 12 +++---- .../lean-runtime/references/numina_runtime.md | 12 ++++--- .../references/specialist_agent_patterns.md | 9 +++--- skills/lean-runtime/scripts/ai4m_lean.py | 4 +-- skills/lean-runtime/scripts/configure_lean.py | 2 +- skills/lean-runtime/scripts/direct_task.py | 2 +- skills/lean-runtime/scripts/smoke_test.py | 6 ++-- skills/lean-runtime/scripts/tool_status.py | 2 +- .../lean-runtime/scripts/verify_delivery.py | 28 ++++++++++++----- skills/lean-runtime/tests/test_cli.py | 25 +++++++++++++++ .../lean-runtime/tests/test_configure_lean.py | 2 +- skills/lean-setup/SKILL.md | 2 +- 26 files changed, 180 insertions(+), 93 deletions(-) create mode 100644 skills/lean-runtime/references/backend_adapter_checklist.md diff --git a/.cursor/rules/lean-formalization.mdc b/.cursor/rules/lean-formalization.mdc index 2a75b04..39f738b 100644 --- a/.cursor/rules/lean-formalization.mdc +++ b/.cursor/rules/lean-formalization.mdc @@ -9,6 +9,6 @@ alwaysApply: false Use `skills/lean-formalization/SKILL.md` as the canonical workflow. -This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker: read/edit Lean, run Lean/Lake, iterate from errors, and validate final patches locally. Official Numina is an optional deployable subagent backend; preserve that deployment/call path but do not make it the default. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/lean-runtime/scripts/` is optional shared tooling and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. +This is a coding-agent-first Lean skill. The coding agent is the primary Lean worker: read/edit Lean, run Lean/Lake, iterate from errors, and validate final patches locally. Official Numina is the only currently supported deployable backend adapter; preserve that deployment/call path but do not make it the default. Archon and other backends are future adapters until their setup, call, credential, mutation, and validation contracts are documented. Match the user's language by default; if the user's language is ambiguous, default to Chinese. Do not treat language switches as task resets. Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input; use the bundled smoke test when no user target is available. Opening readiness should inspect local Lean readiness first; inspect Numina/backend readiness only when the user asks for an optional Lean-specialist backend. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. The helper CLI under `skills/lean-runtime/scripts/` is optional shared tooling and should be used only for environment checks, structured validation, optional Numina readiness/setup, patch review, `sorry` detection, or minimal failure handoff. -Deploy or call the official Numina subagent only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. +Deploy or call the official Numina backend only when the user asks for it or approves it after an explanation. Keep secrets in environment variables or ignored local files. diff --git a/AGENTS.md b/AGENTS.md index 71b5b7d..d81946e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,7 @@ # Agent Instructions Use `skills/lean-setup/SKILL.md` for setup-only tasks such as installing or verifying Lean 4, `elan`, `lake`, or a reusable mathlib workspace. -Use the canonical shared Skill layer at `skills/lean-formalization/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. +Use the canonical shared Skill layer at `skills/lean-formalization/SKILL.md` for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean patch review, optional Lean-specialist backend adapter work currently implemented for official Numina Lean Agent runtime deployment/calls, local Lean validation, and minimal failure handoff. Reusable scripts, examples, prompts, schemas, and references live in the non-user-facing support layer at `skills/lean-runtime/`; install it alongside the two public Skill entrypoints. Core rules: @@ -9,14 +9,14 @@ Core rules: - This is a coding-agent-first Lean skill. - The coding agent is the primary Lean worker. - Setup-only mode should not ask for a theorem target. -- Official Numina is an optional deployable subagent backend. +- Official Numina is the only currently supported deployable backend adapter; Archon and other backends are future adapters until an adapter contract, setup path, call path, and local validation gates are implemented. - Match the user's language by default. - If the user's language is ambiguous, default to Chinese. - Lead the interaction: inspect context, summarize what is ready, recommend the next useful step, and ask at most one blocking question. - Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. - When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. - Use the bundled smoke test when no user target is available. -- Formalization/proof readiness should inspect local Lean readiness and Numina subagent readiness separately. +- Formalization/proof readiness should inspect local Lean readiness first; inspect Numina/backend readiness only when the user asks for an optional Lean-specialist backend. - Setup-only readiness should focus on local Lean/mathlib state, and should mention or inspect Numina only when the user asks for the optional official backend. - Do not require API keys for the default coding-agent path. - Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. diff --git a/CLAUDE.md b/CLAUDE.md index 5d95f5a..b075794 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -18,7 +18,7 @@ Shared helper scripts, references, prompts, schemas, examples, and tests live in skills/lean-runtime/ ``` -Use Claude Code as the primary Lean coding agent. Official Numina is an optional deployable subagent backend; preserve that setup/call path but do not make it the default. +Use Claude Code as the primary Lean coding agent. Official Numina is the only currently supported deployable backend adapter; preserve that setup/call path but do not make it the default. Archon and other backends are future adapters until their setup, call, credential, mutation, and validation contracts are documented. Setup-only mode should create or verify the Lean/mathlib workspace without asking for a theorem target. Match the user's language by default. If the user's language is ambiguous, default to Chinese. @@ -26,9 +26,9 @@ Lead the interaction: inspect context, summarize what is ready, recommend the ne Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Use the bundled smoke test when no user target is available. -Formalization/proof readiness should inspect local Lean readiness and Numina subagent readiness separately. +Formalization/proof readiness should inspect local Lean readiness first; inspect Numina/backend readiness only when the user asks for an optional Lean-specialist backend. Setup-only readiness should focus on local Lean/mathlib state, and should mention or inspect Numina only when the user asks for the optional official backend. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -Deploy or call the official Numina subagent runtime only after explanation and approval. Keep secrets in environment variables or ignored local files. +Deploy or call the official Numina backend runtime only after explanation and approval. Keep secrets in environment variables or ignored local files. diff --git a/GEMINI.md b/GEMINI.md index c0c5ac0..9f25e71 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -12,7 +12,7 @@ For Lean 4 formal verification tasks, use the shared Skill layer at: skills/lean-formalization/SKILL.md ``` -Use Gemini as the primary Lean coding agent. Official Numina is an optional deployable subagent backend; preserve that setup/call path but do not make it the default. +Use Gemini as the primary Lean coding agent. Official Numina is the only currently supported deployable backend adapter; preserve that setup/call path but do not make it the default. Archon and other backends are future adapters until their setup, call, credential, mutation, and validation contracts are documented. Setup-only mode should create or verify the Lean/mathlib workspace without asking for a theorem target. Match the user's language by default. If the user's language is ambiguous, default to Chinese. @@ -20,9 +20,9 @@ Lead the interaction: inspect context, summarize what is ready, recommend the ne Do not treat a language switch as a task reset; keep the current diagnosis and continue leading in the new language. When no target is provided, run or propose a safe local smoke/readiness check before asking for more input. Use the bundled smoke test when no user target is available. -Formalization/proof readiness should inspect local Lean readiness and Numina subagent readiness separately. +Formalization/proof readiness should inspect local Lean readiness first; inspect Numina/backend readiness only when the user asks for an optional Lean-specialist backend. Setup-only readiness should focus on local Lean/mathlib state, and should mention or inspect Numina only when the user asks for the optional official backend. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -The helper CLI under `skills/lean-runtime/scripts/` is optional tooling shared by the two public Skill entrypoints. It can report and configure the official Numina subagent runtime, but the agent should still validate final Lean patches locally. +The helper CLI under `skills/lean-runtime/scripts/` is optional tooling shared by the two public Skill entrypoints. It can report and configure the official Numina backend runtime, but the agent should still validate final Lean patches locally. diff --git a/README.md b/README.md index a4b9e35..5ea2d5f 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ This repository provides two AI4Math Lean skills: Both public skills share the bundled `skills/lean-runtime/` support layer for helper scripts, references, prompts, schemas, examples, and tests. Users invoke only the two public skills; installers should keep `lean-runtime` next to them. -`lean-formalization` is informed by publicly available Lean-specialist agent patterns from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. +`lean-formalization` is informed by publicly available Lean-specialist agent patterns from systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP/MCP integrations, and small iterative proof agents. These are workflow patterns and related work references, not claims that every backend is implemented. + +Currently supported optional backend: official Numina Lean Agent runtime. Future backend adapters may include Archon or other Lean-specialist systems, but do not claim support until deployment, readiness checks, invocation, validation, and failure triage are documented. ## When To Use These Skills @@ -19,11 +21,11 @@ Use these skills when you have: - a Lean project or Lean file that needs inspection; - a theorem statement to transcribe or formalize; - a proof with `sorry`, `admit`, errors, or statement drift risk; -- a need for optional Numina setup mediated by the coding agent. +- a need for an optional Lean-specialist backend mediated by the coding agent; the currently supported deployable backend is official Numina. ## What They Produce -The agent should produce Lean patches, validation summaries, blocked-goal explanations, minimized failures, and optional Numina setup evidence. +The agent should produce Lean patches, validation summaries, blocked-goal explanations, minimized failures, and optional backend setup evidence when the supported official Numina path is requested. ## Installation @@ -79,9 +81,11 @@ Constraints: - Patch review for `sorry`, `admit`, newly introduced `axiom`, and theorem statement drift. - Minimal failing Lean fragment extraction when a proof is blocked. - Related-work-informed Lean-specialist patterns: theorem-state loops, premise retrieval, bounded proof search, failure memory, validation oracles, and minimal handoff. -- Optional official `project-numina/numina-lean-agent` deployment/call flow, mediated by the coding agent. +- Optional Lean-specialist backend adapter flow, currently implemented for official `project-numina/numina-lean-agent` deployment/calls mediated by the coding agent. + +Numina is optional and is the only built-in deployable backend adapter. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `~/.ai4math/numina-runtime/` by default. -Numina is optional. The public CLI does not expose a parallel `numina-*` workflow; `doctor` reports readiness and `configure --setup-numina --project-name ` performs the reviewed local setup under `~/.ai4math/numina-runtime/` by default. +Future backend adapters can follow `skills/lean-runtime/references/backend_adapter_checklist.md`, but should not be described as supported until deployment, readiness checks, invocation, validation, and failure triage are documented. ## Repository Layout @@ -112,7 +116,7 @@ Lean task -> project inspection -> plan -> approve / revise / reject / skip Use `approve` to run a proposed step, `revise` to update the plan, `reject` to stop the path, and `skip` to move past a phase. The agent should ask before -theorem statement changes, optional Numina setup, source edits, or final proof +theorem statement changes, optional backend setup, source edits, or final proof claims. ## Helper Commands @@ -130,7 +134,7 @@ python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --requir The helper CLI is not the proof engine. The coding agent remains responsible for reading Lean errors, editing proofs, choosing proof strategy, and matching the user's language. -For the optional Numina path, read `skills/lean-runtime/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. +For the supported official Numina backend path, read `skills/lean-runtime/references/numina_runtime.md`. Setup and official runner calls may clone repositories, install tools, or use external model/API credentials, so they should be explained before execution. ## Validate diff --git a/README.zh-CN.md b/README.zh-CN.md index 8114b6b..a9a6f27 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -9,7 +9,9 @@ 两个公开 skill 共享随仓库提供的 `skills/lean-runtime/` 支持层,其中包含 helper scripts、references、prompts、schemas、examples 和 tests。用户只调用两个公开 skill;安装时应让 `lean-runtime` 保持在它们的 sibling 位置。 -`lean-formalization` 采用 coding-agent-first 定位,设计借鉴了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。 +`lean-formalization` 采用 coding-agent-first 定位,设计借鉴了 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 集成和轻量迭代 proof agent 等公开 Lean 专用 agent 的机制。这些是 workflow patterns 和相关工作参考,不表示所有 backend 都已经实现。 + +当前支持的可选 backend:official Numina Lean Agent runtime。未来 backend adapter 可包括 Archon 或其他 Lean-specialist systems,但在 deployment、readiness checks、调用、validation 和 failure triage 文档化前,不要写成已支持。 ## 适合什么任务 @@ -19,11 +21,11 @@ - 需要检查的 Lean project 或 Lean 文件; - 需要转写或形式化的 theorem statement; - 带有 `sorry`、`admit`、errors 或 statement drift 风险的 proof; -- 需要由 coding agent 协调的可选 Numina 设置。 +- 需要由 coding agent 协调的可选 Lean 专用 agent backend;当前支持的可部署 backend 是 official Numina。 ## 会产出什么 -Agent 应产出 Lean patches、validation summaries、blocked-goal explanations、minimized failures 和可选 Numina setup evidence。 +Agent 应产出 Lean patches、validation summaries、blocked-goal explanations、minimized failures,以及在用户要求 supported official Numina 路径时产出可选 backend setup evidence。 ## 安装 @@ -88,11 +90,13 @@ claim 前都应先请求用户确认。 - 只配置环境时,可创建或复用共享 `~/.ai4math/lean-workspace`。 - theorem formalization、proof repair、proof completion 和 `sorry` completion。 - patch review:检查 `sorry`、`admit`、新引入的 `axiom` 和 theorem statement drift。 -- 可选 official `project-numina/numina-lean-agent` runtime 设置和调用。 +- 可选 Lean 专用 agent backend adapter 流程;当前实现的是由 coding agent 协调的 official `project-numina/numina-lean-agent` runtime 设置和调用。 - proof blocked 时抽取最小失败 Lean fragment。 - 借鉴 Lean 专用 agent 模式:theorem-state loop、premise retrieval、bounded proof search、失败记忆、validation oracle 和 minimal handoff。 -Numina 是可选链路。公共 CLI 不提供并行的 `numina-*` workflow;`doctor` 用于报告 readiness,`configure --setup-numina --project-name ` 用于在 review 后执行本地设置,默认位置为 `~/.ai4math/numina-runtime/`。只有当用户明确要求 `Numina`、`official Lean Agent`、批量 proof search 或外部 subagent run 时,才应进入 official Numina backend。 +Numina 是可选链路,也是当前唯一内置可部署 backend adapter。公共 CLI 不提供并行的 `numina-*` workflow;`doctor` 用于报告 readiness,`configure --setup-numina --project-name ` 用于在 review 后执行本地设置,默认位置为 `~/.ai4math/numina-runtime/`。只有当用户明确要求 `Numina`、`official Lean Agent`、批量 proof search 或外部 subagent run 时,才应进入 official Numina backend。 + +未来 backend adapter 可参考 `skills/lean-runtime/references/backend_adapter_checklist.md`,但在 deployment、readiness checks、调用、validation 和 failure triage 文档化前,不要写成已支持。 ## 仓库结构 @@ -127,7 +131,7 @@ python skills/lean-runtime/scripts/ai4m_lean.py verify-delivery --cwd . --requir 辅助 CLI 不是 proof engine。coding agent 仍负责读取 Lean errors、编辑 proofs、选择 proof strategy,并匹配用户语言。 -可选 Numina 路径请读取 `skills/lean-runtime/references/numina_runtime.md`。setup 和 official runner calls 可能 clone repositories、安装工具或使用外部 model/API credentials,因此执行前应先说明。 +受支持的 official Numina backend 路径请读取 `skills/lean-runtime/references/numina_runtime.md`。setup 和 official runner calls 可能 clone repositories、安装工具或使用外部 model/API credentials,因此执行前应先说明。 ## 维护者检查 diff --git a/SKILL.md b/SKILL.md index b3dbf36..8d7ca98 100644 --- a/SKILL.md +++ b/SKILL.md @@ -1,6 +1,6 @@ --- name: lean-formalization -description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, optional official Numina deployment/calls, or local Lean validation. +description: Use when a coding agent needs Lean 4 formalization, proof repair, theorem transcription, sorry completion, Lean patch review, optional Lean-specialist backend adapter work currently implemented for official Numina deployment/calls, or local Lean validation. --- # Lean Formalization @@ -32,5 +32,5 @@ skills/lean-setup/SKILL.md - Preserve theorem statements unless the user approves a change. - Reject final patches containing `sorry`, `admit`, or newly introduced `axiom`. -- Explain and approve optional Numina runtime setup before executing it. +- Explain and approve optional backend runtime setup before executing it; currently supported optional backend: official Numina Lean Agent runtime. - Validate final Lean patches locally when possible. diff --git a/skills/lean-formalization/README.md b/skills/lean-formalization/README.md index 4fac1d3..d4bd6f7 100644 --- a/skills/lean-formalization/README.md +++ b/skills/lean-formalization/README.md @@ -2,13 +2,14 @@ `lean-formalization` is the concrete AI4Math skill entrypoint for Lean 4 formalization, proof repair, theorem transcription, `sorry` completion, Lean -patch review, local validation, and optional official Numina runtime work. +patch review, local validation, and optional Lean-specialist backend adapter +work currently implemented for official Numina. ## Entry Point Start with [`SKILL.md`](SKILL.md). It defines the coding-agent-first workflow, -the optional Numina boundary, safety rules, and the reference files to load for -specific tasks. +the optional backend boundary, safety rules, and the reference files to load +for specific tasks. ## Runtime Support diff --git a/skills/lean-formalization/SKILL.md b/skills/lean-formalization/SKILL.md index 16c19e1..505baf5 100644 --- a/skills/lean-formalization/SKILL.md +++ b/skills/lean-formalization/SKILL.md @@ -1,11 +1,11 @@ --- name: lean-formalization -description: Use for interactive Lean 4 formal verification by coding agents with reusable Lean/mathlib workspaces, theorem formalization, proof repair, sorry completion, patch review, optional official Numina subagent deployment/calls, and minimal failure handoff. +description: Use for interactive Lean 4 formal verification by coding agents with reusable Lean/mathlib workspaces, theorem formalization, proof repair, sorry completion, patch review, optional Lean-specialist backend adapter support currently implemented for official Numina deployment/calls, and minimal failure handoff. --- # Lean Formalization -Use this skill when the user wants a coding agent to do Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or optional official Numina Lean Agent/subagent work. +Use this skill when the user wants a coding agent to do Lean 4 formalization, proof repair, theorem transcription, sorry completion, review of a Lean patch, or optional Lean-specialist backend work. If the user only wants Lean 4, `elan`, `lake`, or a reusable mathlib workspace configured, use the sibling `../lean-setup/SKILL.md` entrypoint and do not ask for a theorem target. @@ -15,31 +15,31 @@ This is a coding-agent-first Lean skill. The coding agent is the primary Lean wo Incorporate publicly documented Lean-specialist agent patterns into the default coding-agent workflow. Use systems such as Numina, LeanDojo/ReProver, LeanCopilot, COPRA-style proof search, Lean LSP, MCP, and lightweight iterative proof agents as related-work references for mechanisms such as project gating, statement normalization, theorem-state loops, premise retrieval, bounded tactic/proof search, validation oracles, failure memory, and minimized handoff. Treat specialist-agent patterns as mechanisms, not mandatory external services. -Official Numina is an optional deployable subagent backend. Keep the official Numina deployment/call path available for users who ask for the official Lean Agent, batch proof search, or an external subagent run. Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run. +Lean-specialist backend adapters are optional escalation paths. Currently supported optional backend: official Numina Lean Agent runtime. Official Numina is the only currently supported deployable backend adapter; Archon and other backends are future adapters until an adapter contract, setup path, call path, and local validation gates are implemented. Future backend adapters may include Archon or other Lean-specialist systems, but do not claim support until deployment, readiness checks, invocation, validation, and failure triage are documented. Use the official Numina adapter only when the user asks for the official Lean Agent, Numina, batch proof search, or an approved external subagent run. Match the user's language by default. If the user's language is ambiguous, default to Chinese. If the user writes Chinese, respond in Chinese from the first turn unless they ask otherwise. A language switch is not a task reset. Keep the current environment state, prior diagnosis, and recommended next action, then continue leading in the new language. Lead the interaction; do not wait for the user to drive every step. When the user's request is broad or underspecified, first orient yourself to the Lean project/workspace state, then propose the next useful action in plain language. Do not open with a passive "send me the file" checklist when you can inspect context or offer a concrete starting path. -If no target is available, run or propose a safe local smoke/readiness check. Use the bundled smoke test when no user target is available. Then recommend a default path, such as checking the shared Lean workspace, running the built-in smoke theorem, inspecting a Lean project, or checking Numina subagent readiness if the user wants that path. Avoid ending with only "send me a file" or an equivalent passive handoff. +If no target is available, run or propose a safe local smoke/readiness check. Use the bundled smoke test when no user target is available. Then recommend a default path, such as checking the shared Lean workspace, running the built-in smoke theorem, or inspecting a Lean project. Check backend readiness only when the user wants an optional Lean-specialist backend path. Avoid ending with only "send me a file" or an equivalent passive handoff. The bundled CLI is a helper toolbox, not the workflow driver. Prefer normal coding-agent judgment, direct file edits, `rg`, Lean/Lake validation, and repository context. Use helper commands only when their deterministic output is useful. -Use official Numina through a human-in-the-loop subagent workflow. Numina lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, proxy/MCP, and upstream runner implications before running setup or calling the official runner. Do not turn helper commands into a closed proof workflow. +Use official Numina through a human-in-the-loop backend adapter workflow. Numina lives under shared local state at `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`; the coding agent explains clone, setup, API-key, proxy/MCP, and upstream runner implications before running setup or calling the official runner. Future backend adapters must follow `../lean-runtime/references/backend_adapter_checklist.md`. Do not turn helper commands into a closed proof workflow. -Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. +Opening readiness should inspect local Lean readiness first; inspect Numina or another backend readiness only when the user asks for an optional Lean-specialist backend. Do not require API keys for the default coding-agent path. Default coding-agent Lean work must not require any backend adapter. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. -Do not remove the official Numina subagent path. Treat it as an optional backend with explicit approval, while keeping the direct coding-agent Lean workflow useful without external APIs. +Do not remove the official Numina subagent path. Treat it as the supported optional backend with explicit approval, while keeping the direct coding-agent Lean workflow useful without external APIs. ## Agent Playbook 1. Start by orienting the session: inspect the current repository/workspace when possible, distinguish existing Lake project, shared Lean workspace, local Lean validation readiness, Numina runtime, and Numina credentials/auth, and summarize what is already usable. Treat upstream Numina example projects as demos only; do not let their pinned `lean-toolchain` make the shared workspace look broken. -2. If the user has not provided a precise target, offer a small next-step menu such as run the bundled smoke test, repair an existing Lean file, formalize a natural-language/LaTeX theorem, inspect a Lean project, configure Numina credentials, run a Numina readiness check, or prepare the shared workspace as a Numina target. Recommend one default path based on what inspection found. +2. If the user has not provided a precise target, offer a small next-step menu such as run the bundled smoke test, repair an existing Lean file, formalize a natural-language/LaTeX theorem, or inspect a Lean project. Include Numina readiness or credential setup only when the user asks for the optional official backend path. Recommend one default path based on what inspection found. 3. Ask at most one blocking question at a time. Prefer a concrete recommendation plus one decision question over a list of required inputs. -4. Understand the user's intent: direct coding-agent repair/formalization, configure Numina, call Numina, repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. +4. Understand the user's intent: direct coding-agent repair/formalization, configure the supported official Numina backend, call Numina, repair a file, formalize a statement, prove a target, complete `sorry`, review a patch, batch a folder, or minimize a failure. 5. Locate the relevant Lean project, files, declarations, imports, and current errors. Use the user's existing Lake project when available; otherwise use the shared workspace as the coding-agent project context and optional Numina target project. 6. For standalone files, use or create the shared workspace `${AI4MATH_HOME:-~/.ai4math}/lean-workspace`; do not create a second project-local workspace unless the user asks for isolation. -7. When reporting readiness, lead with local Lean readiness, then Numina subagent readiness. If Numina credentials are missing, say that only the optional Numina subagent path needs configuration. +7. When reporting readiness, lead with local Lean readiness. Report Numina readiness only when the optional official backend path is requested. If Numina credentials are missing, say that only the optional Numina backend path needs configuration. 8. Before a Numina setup or run, inspect `doctor` readiness, explain the deployment/call, target project, prompt, result directory, credential/proxy/MCP state, and local validation plan; proceed only after approval. 9. For natural-language or LaTeX input, draft the Lean declaration and ask for confirmation before long proof work. 10. Edit Lean directly in small steps for the default coding-agent path, using incorporated specialist-agent patterns such as theorem-state inspection, nearby lemma retrieval, bounded proof attempts, failed-strategy notes, and minimal failure extraction. If Numina is approved, call the official Numina runner for proof search/formalization, then run Lean/Lake validation and patch safety checks before accepting results. @@ -51,21 +51,21 @@ Do not remove the official Numina subagent path. Treat it as an optional backend Use `python ../lean-runtime/scripts/ai4m_lean.py ` when it saves effort or reduces risk: -- `env` / `doctor`: inspect Lean workspace, local tool availability, and Numina subagent readiness. +- `env` / `doctor`: inspect Lean workspace, local tool availability, and supported Numina backend readiness. - `configure --create-workspace`: create or reuse the shared managed workspace. - `configure --setup-numina --project-name `: after user approval, clone/configure the official Numina runtime under `${AI4MATH_HOME:-~/.ai4math}/numina-runtime/`. - `smoke-test`: run the bundled `../lean-runtime/examples/smoke/NuminaSmoke.lean` target in the shared workspace without external API calls. - `check`: run a structured Lean/Lake validation. - `review` / `detect-sorry`: guard against placeholders, axioms, and statement drift. - `minimize-failure`: extract a compact failing Lean fragment. -- `prove` / `formalize` / `repair` / `complete-sorries` / `batch`: optional dry-run task envelopes for coding-agent bookkeeping; use the official Numina runner only when the optional subagent path is approved. +- `prove` / `formalize` / `repair` / `complete-sorries` / `batch`: optional dry-run task envelopes for coding-agent bookkeeping; use the official Numina runner only when the optional backend path is approved. - `verify-delivery`: validate this skill package. All helper commands emit machine-readable JSON on stdout. Human-readable diagnostics go to stderr or log files. ## Numina Runtime -When using the official Numina runtime, follow `../lean-runtime/references/numina_runtime.md`. For auth/proxy/MCP/failure triage, follow `../lean-runtime/references/numina_subagent_troubleshooting.md`. Proof strategy is a human-in-the-loop process with the user, the coding agent, local Lean checks, and, when approved, the official Numina runner as an optional subagent backend. +When using the official Numina runtime, follow `../lean-runtime/references/numina_runtime.md`. For auth/proxy/MCP/failure triage, follow `../lean-runtime/references/numina_subagent_troubleshooting.md`. For future backend adapters, follow `../lean-runtime/references/backend_adapter_checklist.md`. Proof strategy is a human-in-the-loop process with the user, the coding agent, local Lean checks, and, when approved, the official Numina runner as the currently supported optional backend. ## Safety Rules @@ -86,6 +86,7 @@ When using the official Numina runtime, follow `../lean-runtime/references/numin - Read `../lean-runtime/references/lean_runtime_configuration.md` when setting up or diagnosing the reusable Lean workspace. - Read `../lean-runtime/references/numina_runtime.md` when the user wants the official Numina deployment/call path. - Read `../lean-runtime/references/numina_subagent_troubleshooting.md` when Numina auth, proxy, MCP, or runner failures appear. +- Read `../lean-runtime/references/backend_adapter_checklist.md` before describing Archon or any other future backend as supported. - Read `../lean-runtime/references/interactive_orchestration.md` when guiding user intake and task decomposition. - Read `../lean-runtime/references/review_checklist.md` before accepting a Lean patch. - Read `../lean-runtime/references/failure_taxonomy.md` when reporting a blocked proof. diff --git a/skills/lean-formalization/agents/openai.yaml b/skills/lean-formalization/agents/openai.yaml index 88540b8..a45bf9b 100644 --- a/skills/lean-formalization/agents/openai.yaml +++ b/skills/lean-formalization/agents/openai.yaml @@ -1,3 +1,3 @@ display_name: Lean Formalization -short_description: Interactive Lean 4 verification for coding agents that incorporate Lean-specialist agent patterns, with optional official Numina subagent calls. -default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。该 skill 参考并整合 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 等公开 Lean 专用 agent 的机制:项目门禁、statement normalization、theorem-state loop、premise retrieval、bounded search、失败记忆、Lean/Lake oracle 和 minimal failure handoff。Numina 是可部署的可选 subagent backend;只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入这条链路。开场分别检查本地 Lean/shared workspace readiness 和 Numina subagent readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina subagent 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 +short_description: Interactive Lean 4 verification for coding agents that incorporate Lean-specialist agent patterns, with optional backend adapter support currently implemented for official Numina. +default_prompt: 请用中文开始并主动引导 Lean 会话;如果用户明确使用其他语言,再切换到用户语言。默认走 coding agent Lean 工作流:你直接读写 Lean、运行 Lean/Lake、根据报错迭代并验收无 sorry/admit/axiom。该 skill 参考并整合 Numina、LeanDojo/ReProver、LeanCopilot、COPRA-style proof search、Lean LSP/MCP 等公开 Lean 专用 agent 的机制:项目门禁、statement normalization、theorem-state loop、premise retrieval、bounded search、失败记忆、Lean/Lake oracle 和 minimal failure handoff。可选 Lean 专用 backend adapter 目前只承诺 official Numina adapter 已支持;Archon 和其他 backend 只能作为 future adapters,除非部署、readiness、调用、validation、failure triage 已文档化。只有用户要求 official Lean Agent、Numina、batch proof search 或外部 subagent 时才进入 backend 链路。默认开场检查本地 Lean/shared workspace readiness;仅当用户要求 optional backend 时再检查 Numina readiness。没有用户目标时先使用内置 smoke-test 验证本地 Lean/mathlib 验收链路。默认 coding-agent 路径不要求 API key;Numina backend 调用前要说明 target、prompt、max rounds、result dir、Claude/API/proxy/MCP 状态并获得批准。一次最多问一个阻塞问题。 diff --git a/skills/lean-runtime/references/backend_adapter_checklist.md b/skills/lean-runtime/references/backend_adapter_checklist.md new file mode 100644 index 0000000..7c2151d --- /dev/null +++ b/skills/lean-runtime/references/backend_adapter_checklist.md @@ -0,0 +1,31 @@ +# Backend Adapter Checklist + +Use this checklist before claiming that a Lean-specialist backend is supported. Backend adapters are optional escalation paths; default coding-agent Lean work must not require any backend adapter. + +## Support Status + +- `supported`: setup, readiness checks, invocation, local validation, and failure triage are documented and guarded. +- `experimental`: partial adapter exists, but the agent must explain gaps and request approval before use. +- `future`: related work or candidate backend only; do not claim support or call it automatically. + +Currently supported optional backend: official Numina Lean Agent runtime. + +Future backend adapters may include Archon or other Lean-specialist systems, but do not claim support until deployment, readiness checks, invocation, validation, and failure triage are documented. + +## Adapter Contract + +Document all of the following before moving a backend out of `future`: + +- Name, upstream source, license, and support status. +- Trigger phrases that justify using this backend. +- Setup location, install commands, network access, and local state written. +- Required tools, credentials, API keys, proxy settings, or MCP scope. +- Readiness checks that do not call external model APIs. +- Invocation command, working directory, target project/file/folder, prompt, result directory, and round limits. +- Mutation boundary: which files may be changed, where generated outputs go, and which actions require approval. +- Local validation gate: Lean/Lake check, `detect-sorry`, `review`, and theorem statement drift checks. +- Failure triage: auth, proxy, MCP, toolchain, runner, timeout, and fallback to the coding-agent path. + +## Non-Claim Rule + +Do not claim support for a backend adapter unless its setup, call, credential, mutation, and validation contracts are documented. Unimplemented adapters may be cited as related work or future adapters only. diff --git a/skills/lean-runtime/references/direct_lean_workflow.md b/skills/lean-runtime/references/direct_lean_workflow.md index aeb3d22..a5fb44d 100644 --- a/skills/lean-runtime/references/direct_lean_workflow.md +++ b/skills/lean-runtime/references/direct_lean_workflow.md @@ -1,6 +1,6 @@ # Direct Coding-Agent Lean Workflow -This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. It incorporates Lean-specialist agent patterns into local work: theorem-state loops, premise retrieval, bounded proof attempts, failed-strategy memory, and minimal failure handoff. Official Numina remains available as an optional deployable subagent backend, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. +This is the default workflow. The coding agent reads and edits Lean directly, runs Lean/Lake checks, and iterates from concrete errors/goals. It incorporates Lean-specialist agent patterns into local work: theorem-state loops, premise retrieval, bounded proof attempts, failed-strategy memory, and minimal failure handoff. Official Numina remains available as the currently supported optional Lean-specialist backend adapter, but it is not required for ordinary Lean formalization, proof repair, or sorry completion. ## Guidance-First Loop @@ -27,7 +27,7 @@ Use helpers for mechanical checks: - failure handoff: `minimize-failure`; - package QA: `verify-delivery`. -Do not route creative proof search through helper commands. `prove`, `formalize`, `repair`, `complete-sorries`, and `batch` only produce optional task envelopes for bookkeeping. Use the official Numina runner only when the optional subagent path is approved. +Do not route creative proof search through helper commands. `prove`, `formalize`, `repair`, `complete-sorries`, and `batch` only produce optional task envelopes for bookkeeping. Use the official Numina runner only when the optional backend path is approved. ## Workspace Choice diff --git a/skills/lean-runtime/references/interactive_orchestration.md b/skills/lean-runtime/references/interactive_orchestration.md index bd85e4d..c0f6fe6 100644 --- a/skills/lean-runtime/references/interactive_orchestration.md +++ b/skills/lean-runtime/references/interactive_orchestration.md @@ -1,14 +1,14 @@ # Interactive Orchestration -The coordinating coding agent owns user interaction, Lean proof/formalization work, incorporated Lean-specialist agent patterns, optional Numina orchestration, and final validation. It can delegate proof search/formalization to the official Numina subagent when the user asks for that backend. +The coordinating coding agent owns user interaction, Lean proof/formalization work, incorporated Lean-specialist agent patterns, optional Lean-specialist backend adapter orchestration, and final validation. It can delegate proof search/formalization to the official Numina adapter when the user asks for that currently supported backend. -This reference covers the guidance layer: session opening, intake, task classification, direct coding-agent Lean work, specialist-agent pattern selection, optional Numina deployment/calls, local Lean validation, result review, bounded iteration, and minimal failure handoff. +This reference covers the guidance layer: session opening, intake, task classification, direct coding-agent Lean work, specialist-agent pattern selection, optional Lean-specialist backend adapter deployment/calls currently only for official Numina, local Lean validation, result review, bounded iteration, and minimal failure handoff. ## Session Opening If the user's language is ambiguous, default to Chinese. The skill display name, repository name, or command name is not enough evidence to choose English. -This is a coding-agent-first Lean skill. Official Numina is an optional deployable subagent backend. +This is a coding-agent-first Lean skill. Official Numina is the only currently supported deployable backend adapter; Archon and other backends are future adapters until an adapter contract, setup path, call path, and local validation gates are implemented. The default coding-agent path should still absorb Lean-specialist agent mechanisms: project gating, statement normalization, theorem-state loops, premise retrieval, bounded proof search, failed-strategy memory, Lean/Lake validation, and minimized failure handoff. @@ -17,10 +17,10 @@ Lead the interaction; do not wait for the user to drive every step. On a broad r - inspect whether the current directory is a Lake project; - check whether the shared `${AI4MATH_HOME:-~/.ai4math}/lean-workspace` exists; - inspect local Lean/Lake readiness and shared workspace state; -- inspect Numina runtime, upstream checkout, tools, and credential/auth readiness separately; +- inspect Numina runtime, upstream checkout, tools, and credential/auth readiness only when the user asks for the optional official backend; - say what can be done immediately and what would require confirmation. -Opening readiness should inspect local Lean readiness and Numina subagent readiness separately. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. +Opening readiness should inspect local Lean readiness first. Inspect Numina or another backend readiness only when the user asks for an optional Lean-specialist backend. Do not require API keys for the default coding-agent path. Shared workspace is the default Lean project context; Numina may target it instead of upstream examples. When checking Numina, distinguish runtime readiness from upstream demo readiness. The runtime can be usable with the shared Lean workspace even if an upstream example or benchmark pins a different `lean-toolchain`. Report that as an example-project issue, not as a failure of the shared environment. @@ -34,10 +34,10 @@ If no precise target is provided, offer a small menu and recommend one path. For - repair or complete an existing Lean file with the coding agent; - formalize a natural-language or LaTeX theorem with the coding agent; - inspect a Lean/Lake project and summarize readiness; -- configure missing Numina credentials/auth; -- run a Numina readiness check; -- prepare the shared workspace as the Numina target project; -- call Numina on a natural-language/LaTeX theorem or Lean file. +- if the user asks for the optional official backend, configure missing Numina credentials/auth; +- if the user asks for the optional official backend, run a Numina readiness check; +- if the user asks for the optional official backend, prepare the shared workspace as the Numina target project; +- if the user asks for the optional official backend, call Numina on a natural-language/LaTeX theorem or Lean file. Ask at most one blocking question at a time. A good opening ends with one decision question, not a checklist. @@ -49,23 +49,25 @@ Ask only when not inferable: - What target file/folder and declaration should be used? - Is changing the theorem statement allowed? - Should standalone work use the reusable managed workspace? -- Should we configure/call Numina now, or only inspect readiness? +- If you want the optional official backend, should we configure/call Numina now, or only inspect readiness? - For natural-language or LaTeX input, what statement should be considered authoritative? Prefer asking these only after orientation. If the repository already reveals the likely next step, state the recommendation and ask for confirmation. ## Decomposition -Break large requests into small Lean targets that the coding agent can work on directly, and that Numina can run against if the optional subagent path is approved. Each target should be checkable afterward with Lean/Lake commands or the helper `check` command. +Break large requests into small Lean targets that the coding agent can work on directly, and that Numina can run against if the optional backend path is approved. Each target should be checkable afterward with Lean/Lake commands or the helper `check` command. For natural-language or LaTeX statements, draft the Lean declaration first and ask for confirmation before long proof work. Once the declaration is confirmed, treat statement preservation as a hard guardrail. -## Numina Run +## Backend Run Before an official Numina call, state the target project/file, prompt file, max rounds, result directory, credential/proxy/MCP state, and validation plan. Ask for approval before any external model call or runtime mutation. After Numina returns, inspect changed Lean files, run local Lean/Lake validation, and reject results containing `sorry`, `admit`, new `axiom`, or unapproved theorem statement changes. +Future backend adapters must satisfy `backend_adapter_checklist.md` before they are described as supported or called. + ## Iteration Policy Stop when: @@ -73,7 +75,7 @@ Stop when: - validation succeeds without `sorry`, `admit`, or new `axiom`; - max local iterations are reached; - Lean workspace setup is missing or broken; -- optional Numina credentials/auth are missing and the user specifically requires Numina; +- official Numina backend credentials/auth are missing and the user specifically requires Numina; - the remaining error requires a human mathematical decision; - the only path forward would weaken the theorem statement without approval. diff --git a/skills/lean-runtime/references/lean_runtime_configuration.md b/skills/lean-runtime/references/lean_runtime_configuration.md index f0c080f..93544d1 100644 --- a/skills/lean-runtime/references/lean_runtime_configuration.md +++ b/skills/lean-runtime/references/lean_runtime_configuration.md @@ -1,6 +1,6 @@ # Lean Runtime Configuration -This skill uses a coding-agent Lean workflow by default. Local Lean/Lake is the primary validation layer. Official Numina is an optional deployable subagent backend under ignored shared local state; see `numina_runtime.md` for deployment and call details. +This skill uses a coding-agent Lean workflow by default. Local Lean/Lake is the primary validation layer. Official Numina is the currently supported optional Lean-specialist backend adapter under ignored shared local state; see `numina_runtime.md` for deployment and call details. ## Shared Layout @@ -13,7 +13,7 @@ ${AI4MATH_HOME:-~/.ai4math}/ └── failures/ ``` -Repository-local machine settings still live under `/.ai4math/` and should not be committed. The reusable Lean workspace and optional Numina runtime are shared by default so standalone tasks do not create a fresh workspace in every project. +Repository-local machine settings still live under `/.ai4math/` and should not be committed. The reusable Lean workspace and supported official Numina backend runtime are shared by default so standalone tasks do not create a fresh workspace in every project. ## Tool Checks @@ -24,7 +24,7 @@ python skills/lean-runtime/scripts/ai4m_lean.py doctor --cwd . python skills/lean-runtime/scripts/ai4m_lean.py env --cwd . ``` -Required default workflow tools are `git`, `python3`, `elan`, `lean`, and `lake`. Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Official Numina subagent calls need a working Claude CLI/auth path and may need additional API keys for search/tool skills. +Required default workflow tools are `git`, `python3`, `elan`, `lean`, and `lake`. Numina setup additionally reports `curl`, `uv`, and `claude` readiness. Official Numina backend calls need a working Claude CLI/auth path and may need additional API keys for search/tool skills. ## Reusable Lean Workspace diff --git a/skills/lean-runtime/references/numina_reverse_analysis.md b/skills/lean-runtime/references/numina_reverse_analysis.md index f26dcd8..0714b29 100644 --- a/skills/lean-runtime/references/numina_reverse_analysis.md +++ b/skills/lean-runtime/references/numina_reverse_analysis.md @@ -8,11 +8,11 @@ This reference records how this coding-agent Lean skill incorporates mechanisms - Result repository: https://github.com/project-numina/Numina-Putnam2025 - Paper reference: https://arxiv.org/abs/2601.14027 -The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to incorporate reusable Lean-agent mechanisms into a comprehensive coding-agent skill while preserving a deployable path to the official Numina runtime when the user wants a subagent. +The goal is not to copy Numina prompts or reimplement Numina proof search. The goal is to incorporate reusable Lean-agent mechanisms into a comprehensive coding-agent skill while preserving a deployable path to the official Numina runtime as the currently supported optional backend adapter. ## Incorporated Patterns -1. Use a coding agent as the primary Lean worker, with Numina available as an optional subagent. +1. Use a coding agent as the primary Lean worker, with Numina available as the supported optional backend adapter. 2. Keep Lean/Lake validation as the correctness oracle. 3. Treat theorem statement preservation as a first-class safety check. 4. Work in bounded rounds with a clear stopping condition. @@ -22,7 +22,7 @@ The goal is not to copy Numina prompts or reimplement Numina proof search. The g ## Optional Runtime State -The default AI4Math coding-agent loop does not require these runtime dependencies, but the optional official Numina subagent path does: +The default AI4Math coding-agent loop does not require these runtime dependencies, but the supported official Numina backend path does: - upstream Numina repository checkout; - Numina Python environment; @@ -43,9 +43,9 @@ flowchart TD D --> E["Run Lean/Lake check"] E --> F{"Verified without unsafe placeholders?"} F -->|yes| G["Review patch and return result"] - F -->|no| H{"Use local iteration or approved Numina subagent?"} + F -->|no| H{"Use local iteration or approved Numina backend?"} H -->|yes| D - H -->|Numina| N["Call official Numina subagent after approval"] + H -->|Numina| N["Call official Numina backend after approval"] N --> E H -->|blocked| I["Extract minimal failure and report exact errors/goals"] ``` @@ -76,5 +76,5 @@ If a future agent reads this file during normal Lean work, the default action it 1. verify local Lean readiness; 2. prepare the target in the user's Lake project or shared workspace; 3. edit/check directly as a coding agent; -4. use official Numina only if the user asks for the subagent path or it is approved; +4. use official Numina only if the user asks for the supported backend path or it is approved; 5. return a verified patch or minimal failure. diff --git a/skills/lean-runtime/references/numina_runtime.md b/skills/lean-runtime/references/numina_runtime.md index 6052384..297ff7d 100644 --- a/skills/lean-runtime/references/numina_runtime.md +++ b/skills/lean-runtime/references/numina_runtime.md @@ -1,10 +1,14 @@ -# Optional Official Numina Subagent Runtime +# Optional Official Numina Backend Adapter -This skill keeps the official `project-numina/numina-lean-agent` repository as an optional deployable subagent backend. The default path is coding-agent Lean work with local Lean/Lake validation; Numina is used when the user asks for the official Lean Agent, batch proof search, or an external subagent run. +This skill keeps the official `project-numina/numina-lean-agent` repository as the currently supported optional Lean-specialist backend adapter. The default path is coding-agent Lean work with local Lean/Lake validation; Numina is used when the user asks for the official Lean Agent, Numina, batch proof search, or an approved external subagent run. + +Currently supported optional backend: official Numina Lean Agent runtime. + +Future backend adapters may include Archon or other Lean-specialist systems, but do not claim support until deployment, readiness checks, invocation, validation, and failure triage are documented. See `backend_adapter_checklist.md` before describing any future backend as supported. ## Agent Flow -1. Clarify the target: configure Numina, call Numina on a Lean project/file/folder, validate Numina output, or continue with the default coding-agent path. +1. Clarify the target: configure the supported official Numina adapter, call Numina on a Lean project/file/folder, validate Numina output, or continue with the default coding-agent path. 2. Run `doctor --cwd .` when useful and read the `numina` readiness block before recommending a path. 3. Explain what setup may do: clone the official repository, run `tutorial/setup.sh`, install or use `elan`, `lake`, `curl`, `uv`, and `claude`, and require model/API credentials or Claude CLI auth for calls. 4. After approval, run `configure --cwd . --setup-numina --project-name `. Use `--dry-run` first when the user wants to review commands. @@ -26,7 +30,7 @@ Do not commit runtime state, API keys, generated results, or local machine paths Claude authentication can come from the user's normal Claude CLI login or environment variables such as `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`. Numina's CLI skills may also need `GEMINI_API_KEY`, `OPENAI_API_KEY`, `LEAN_LEANDEX_API_KEY`, or `AXLE_API_KEY`. -If the user asks whether API keys are needed, distinguish the two paths: the default coding-agent Lean workflow and local Lean validation do not need API keys; official Numina subagent calls need a working Claude CLI/auth path and may need additional keys for search/tool skills. +If the user asks whether API keys are needed, distinguish the two paths: the default coding-agent Lean workflow and local Lean validation do not need API keys; official Numina backend calls need a working Claude CLI/auth path and may need additional keys for search/tool skills. The helper readiness report redacts values and only reports whether keys appear configured. diff --git a/skills/lean-runtime/references/specialist_agent_patterns.md b/skills/lean-runtime/references/specialist_agent_patterns.md index 8f01667..40e4765 100644 --- a/skills/lean-runtime/references/specialist_agent_patterns.md +++ b/skills/lean-runtime/references/specialist_agent_patterns.md @@ -29,7 +29,7 @@ Public source anchors: 5. Use bounded search: try a small number of plausible tactic/proof routes; record failed routes so the agent does not cycle. 6. Retrieve before inventing: search existing project/mathlib names and nearby proofs before adding helper lemmas. 7. Validate as oracle: Lean/Lake success is required; final patches must not contain `sorry`, `admit`, new `axiom`, or unapproved statement drift. -8. Escalate deliberately: call optional Numina or another specialist backend only after explaining target, credentials/proxy/MCP state, result directory, and validation plan. +8. Escalate deliberately: call the supported official Numina adapter, or a future backend adapter only after that adapter has an explicit contract and validation gates, and only after explaining target, credentials/proxy/MCP state, result directory, and validation plan. 9. Hand off minimally: when blocked, return the smallest failing Lean fragment, exact goals/errors, tried routes, and the next mathematical decision. ## Pattern Map @@ -41,7 +41,7 @@ Public source anchors: | Premise retrieval | `rg`, nearby imports/proofs, project declarations, optional external search | | Bounded proof attempts | `max_rounds`, local iteration caps, failed-strategy notes | | Backtracking/failure memory | Record tried tactic families and rejected statement changes | -| External proof backend | Optional official Numina subagent, never required for default work | +| Lean-specialist backend adapter | Optional official Numina adapter is supported; Archon and other backends are future adapters, never required for default work | | Validation oracle | Lean/Lake plus `review` and `detect-sorry` | | Failure artifact | `minimize-failure` and exact errors/goals | @@ -49,7 +49,7 @@ Public source anchors: Default to integrated local patterns. Escalate to a real specialist backend only when: -- the user asks for Numina, official Lean Agent, batch proof search, or an external subagent; +- the user asks for Numina, official Lean Agent, batch proof search, or an approved external subagent; - local bounded attempts are cycling and the user approves a backend call; - the required credentials, proxy, MCP scope, and target project are understood; - all backend output will still be reviewed and checked locally. @@ -57,7 +57,8 @@ Default to integrated local patterns. Escalate to a real specialist backend only ## Anti-Patterns - Do not replace proof work with a CLI workflow that only asks the user for more input. -- Do not treat a missing Numina key as blocking ordinary coding-agent Lean work. +- Do not treat a missing Numina key or backend adapter as blocking ordinary coding-agent Lean work. - Do not copy upstream prompts or claim hidden benchmark behavior. - Do not add helper lemmas or theorem statement changes just to make a proof easier unless the user approves. - Do not let an external backend output bypass local Lean validation and patch review. +- Do not claim support for a backend adapter unless its setup, call, credential, mutation, and validation contracts are documented. diff --git a/skills/lean-runtime/scripts/ai4m_lean.py b/skills/lean-runtime/scripts/ai4m_lean.py index e7cae6f..95e96ee 100644 --- a/skills/lean-runtime/scripts/ai4m_lean.py +++ b/skills/lean-runtime/scripts/ai4m_lean.py @@ -52,10 +52,10 @@ def add_common(parser: argparse.ArgumentParser) -> None: def build_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description="AI4Math coding-agent Lean skill CLI with optional Numina subagent orchestration") + parser = argparse.ArgumentParser(description="AI4Math coding-agent Lean skill CLI with optional Lean-specialist backend adapter support") sub = parser.add_subparsers(dest="command", required=True) - env = sub.add_parser("env", help="Inspect Lean workspace and optional Numina subagent environment") + env = sub.add_parser("env", help="Inspect Lean workspace and supported optional backend environment") add_common(env) env.add_argument("--target", default=None) diff --git a/skills/lean-runtime/scripts/configure_lean.py b/skills/lean-runtime/scripts/configure_lean.py index 1da0918..badd59e 100644 --- a/skills/lean-runtime/scripts/configure_lean.py +++ b/skills/lean-runtime/scripts/configure_lean.py @@ -75,7 +75,7 @@ def inspect_environment(cwd: str | Path = ".", config_path: str | Path | None = "mode": "coding-agent", "backend": "none", "numina_required": False, - "numina_runtime": "optional-subagent-backend", + "numina_runtime": "supported-optional-backend-adapter", }, "lean": { "target": str(target_path), diff --git a/skills/lean-runtime/scripts/direct_task.py b/skills/lean-runtime/scripts/direct_task.py index 26dcc9e..754ab71 100644 --- a/skills/lean-runtime/scripts/direct_task.py +++ b/skills/lean-runtime/scripts/direct_task.py @@ -79,7 +79,7 @@ def build_direct_task( "max_rounds": max_rounds, "missing_config": missing, "required_inputs": ["existing Lake project or shared reusable managed workspace"] if "lean_workspace" in missing else [], - "recommended_next_action": "run configure --create-workspace for the shared workspace or move target into a Lake project" if missing else "coding agent should edit/check directly; use Numina only if the optional subagent path is approved", + "recommended_next_action": "run configure --create-workspace for the shared workspace or move target into a Lake project" if missing else "coding agent should edit/check directly; use Numina only if the supported optional backend path is approved", "direct_workflow": next_actions, } diff --git a/skills/lean-runtime/scripts/smoke_test.py b/skills/lean-runtime/scripts/smoke_test.py index be7720b..d36a005 100644 --- a/skills/lean-runtime/scripts/smoke_test.py +++ b/skills/lean-runtime/scripts/smoke_test.py @@ -39,7 +39,7 @@ def run_smoke_test( "ai4math_numina_smoke_le_succ", ], "external_api_call": False, - "recommended_next_action": "run the bundled smoke target, then start the coding-agent Lean task or discuss the optional Numina subagent path", + "recommended_next_action": "run the bundled smoke target, then start the coding-agent Lean task or discuss the supported optional Numina backend path", } if not workspace_root: return { @@ -64,12 +64,12 @@ def run_smoke_test( "ai4math_numina_smoke_le_succ", ], "external_api_call": False, - "recommended_next_action": "use this verified workspace for the next coding-agent Lean task; call official Numina only if the optional subagent path is approved", + "recommended_next_action": "use this verified workspace for the next coding-agent Lean task; call official Numina only if the optional backend path is approved", } lean_result = run_command(command, cwd=workspace_root, timeout=timeout) result["lean"] = lean_result result["ok"] = bool(lean_result.get("ok")) result["status"] = "ok" if result["ok"] else "lean_smoke_failed" if not result["ok"]: - result["recommended_next_action"] = "inspect the Lean smoke error, then repair the shared workspace before any Lean task or optional Numina call" + result["recommended_next_action"] = "inspect the Lean smoke error, then repair the shared workspace before any Lean task or optional backend call" return result diff --git a/skills/lean-runtime/scripts/tool_status.py b/skills/lean-runtime/scripts/tool_status.py index 05051f6..d0303ff 100644 --- a/skills/lean-runtime/scripts/tool_status.py +++ b/skills/lean-runtime/scripts/tool_status.py @@ -76,4 +76,4 @@ def _recommend( return "install git before using Lake projects with remote dependencies" if missing_lean: return "install Lean/elan before creating the reusable Lean workspace" - return "ready for coding-agent Lean workflow and optional Numina subagent orchestration" + return "ready for coding-agent Lean workflow and supported optional Numina backend adapter orchestration" diff --git a/skills/lean-runtime/scripts/verify_delivery.py b/skills/lean-runtime/scripts/verify_delivery.py index cf9d624..ab1a570 100644 --- a/skills/lean-runtime/scripts/verify_delivery.py +++ b/skills/lean-runtime/scripts/verify_delivery.py @@ -33,6 +33,7 @@ "schemas/result.schema.json", "schemas/config.schema.json", "references/lean_runtime_configuration.md", + "references/backend_adapter_checklist.md", "references/interactive_orchestration.md", "references/direct_lean_workflow.md", "references/specialist_agent_patterns.md", @@ -126,24 +127,32 @@ def _guidance_first_check() -> dict[str, Any]: "## Helper Toolbox", "This is a coding-agent-first Lean skill.", "The coding agent is the primary Lean worker.", - "Official Numina is an optional deployable subagent backend.", + "Lean-specialist backend adapters are optional escalation paths.", + "optional Lean-specialist backend", + "Currently supported optional backend: official Numina Lean Agent runtime", + "Official Numina is the only currently supported deployable backend adapter", + "Archon and other backends are future adapters", + "future adapters until an adapter contract, setup path, call path, and local validation gates are implemented", + "do not claim support until deployment, readiness checks, invocation, validation, and failure triage are documented", + "Default coding-agent Lean work must not require any backend adapter.", + "Use the official Numina adapter only when the user asks for the official Lean Agent, Numina, batch proof search, or an approved external subagent run.", "Default execution mode is coding-agent mode.", "Incorporate publicly documented Lean-specialist agent patterns into the default coding-agent workflow.", "Treat specialist-agent patterns as mechanisms, not mandatory external services.", - "Use Numina when the user asks for the official Lean Agent, batch proof search, or an external subagent run.", "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", "If the user's language is ambiguous, default to Chinese.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", - "Opening readiness should inspect local Lean readiness and Numina subagent readiness separately.", + "Opening readiness should inspect local Lean readiness first", + "inspect Numina or another backend readiness only when the user asks for an optional Lean-specialist backend", "Do not require API keys for the default coding-agent path.", "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "offer a small next-step menu", "Ask at most one blocking question at a time.", "The bundled CLI is a helper toolbox, not the workflow driver.", - "Use official Numina through a human-in-the-loop subagent workflow.", + "Use official Numina through a human-in-the-loop backend adapter workflow.", "Do not turn helper commands into a closed proof workflow.", "Do not remove the official Numina subagent path.", ] @@ -151,14 +160,16 @@ def _guidance_first_check() -> dict[str, Any]: orchestration_required = [ "## Session Opening", "This is a coding-agent-first Lean skill.", - "Official Numina is an optional deployable subagent backend.", + "Official Numina is the only currently supported deployable backend adapter", + "Archon and other backends are future adapters", "The default coding-agent path should still absorb Lean-specialist agent mechanisms:", "Use the bundled smoke test when no user target is available.", "Lead the interaction; do not wait for the user to drive every step.", "A language switch is not a task reset.", "If no target is available, run or propose a safe local smoke/readiness check.", "Avoid ending with only \"send me a file\"", - "Opening readiness should inspect local Lean readiness and Numina subagent readiness separately.", + "Opening readiness should inspect local Lean readiness first", + "Inspect Numina or another backend readiness only when the user asks for an optional Lean-specialist backend.", "Do not require API keys for the default coding-agent path.", "Shared workspace is the default Lean project context; Numina may target it instead of upstream examples.", "A good opening ends with one decision question, not a checklist.", @@ -170,7 +181,10 @@ def _guidance_first_check() -> dict[str, Any]: "如果用户明确使用其他语言", "默认走 coding agent Lean 工作流", "该 skill 参考并整合", - "Numina 是可部署的可选 subagent", + "目前只承诺 official Numina adapter 已支持", + "Archon 和其他 backend 只能作为 future adapters", + "默认开场检查本地 Lean/shared workspace readiness", + "仅当用户要求 optional backend 时再检查 Numina readiness", ] openai_missing = [phrase for phrase in openai_required if phrase not in openai_yaml] return { diff --git a/skills/lean-runtime/tests/test_cli.py b/skills/lean-runtime/tests/test_cli.py index 79e6636..275a8dd 100644 --- a/skills/lean-runtime/tests/test_cli.py +++ b/skills/lean-runtime/tests/test_cli.py @@ -189,6 +189,31 @@ def test_lean_setup_guides_next_step_after_successful_setup(self) -> None: self.assertIn("formalize a natural-language or LaTeX theorem", text) self.assertIn("mention optional Numina only when the user explicitly asks", text) + def test_optional_backend_language_distinguishes_current_and_future_adapters(self) -> None: + repo_root = SKILLS_ROOT.parent + texts = [ + (SKILLS_ROOT / "lean-formalization" / "SKILL.md").read_text(encoding="utf-8"), + (SKILL_ROOT / "references" / "numina_runtime.md").read_text(encoding="utf-8"), + ] + readme_path = repo_root / "README.md" + readme_zh_path = repo_root / "README.zh-CN.md" + if readme_path.exists(): + texts.append(readme_path.read_text(encoding="utf-8")) + + for text in texts: + self.assertIn("optional Lean-specialist backend", text) + self.assertIn("Currently supported optional backend: official Numina Lean Agent runtime", text) + self.assertIn("Future backend adapters", text) + self.assertIn("do not claim support until deployment, readiness checks, invocation, validation, and failure triage are documented", text) + self.assertNotIn("Currently supported optional backend: Archon", text) + + if readme_zh_path.exists(): + readme_zh = readme_zh_path.read_text(encoding="utf-8") + self.assertIn("可选 Lean 专用 agent backend", readme_zh) + self.assertIn("当前支持的可选 backend:official Numina Lean Agent runtime", readme_zh) + self.assertIn("未来 backend adapter", readme_zh) + self.assertIn("不要写成已支持", readme_zh) + def test_package_hygiene_scans_lean_setup_entrypoint(self) -> None: generated = SKILL_ROOT.parent / "lean-setup" / "__pycache__" / "sentinel.pyc" generated.parent.mkdir(exist_ok=True) diff --git a/skills/lean-runtime/tests/test_configure_lean.py b/skills/lean-runtime/tests/test_configure_lean.py index 9ece591..1d5c15f 100644 --- a/skills/lean-runtime/tests/test_configure_lean.py +++ b/skills/lean-runtime/tests/test_configure_lean.py @@ -31,7 +31,7 @@ def test_existing_lean_project_is_coding_agent_ready(self) -> None: self.assertEqual(result["agent"]["mode"], "coding-agent") self.assertEqual(result["agent"]["backend"], "none") self.assertFalse(result["agent"]["numina_required"]) - self.assertEqual(result["agent"]["numina_runtime"], "optional-subagent-backend") + self.assertEqual(result["agent"]["numina_runtime"], "supported-optional-backend-adapter") self.assertEqual(result["missing_config"], []) self.assertIn("numina", result) self.assertIn("readiness", result["numina"]) diff --git a/skills/lean-setup/SKILL.md b/skills/lean-setup/SKILL.md index e2ce7eb..be22520 100644 --- a/skills/lean-setup/SKILL.md +++ b/skills/lean-setup/SKILL.md @@ -33,7 +33,7 @@ Offer a short next-step menu after setup succeeds: - formalize a natural-language or LaTeX theorem; - continue setup-only validation if the user only wants environment readiness. -As a rule, mention optional Numina only when the user explicitly asks for the official Lean Agent, batch proof search, or an external subagent backend; do not make Numina or API keys part of the default next step. +As a rule, mention optional Numina only when the user explicitly asks for the official Lean Agent, batch proof search, or an external backend adapter; do not make Numina or API keys part of the default next step. ## Commands