mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
Add optional science toolbelt probe
This commit is contained in:
parent
f41cf1e9fe
commit
40fbab8aac
6 changed files with 385 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -38,6 +38,7 @@ scripts/venv_unsloth/
|
||||||
**/venv_wgpu/
|
**/venv_wgpu/
|
||||||
**/*.venv/
|
**/*.venv/
|
||||||
**/venv/
|
**/venv/
|
||||||
|
.venv-science/
|
||||||
|
|
||||||
# API Keys and credentials (NEVER track in git)
|
# API Keys and credentials (NEVER track in git)
|
||||||
API KEYS/
|
API KEYS/
|
||||||
|
|
|
||||||
79
docs/optional-science-toolbelt.md
Normal file
79
docs/optional-science-toolbelt.md
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
# Optional Science Toolbelt
|
||||||
|
|
||||||
|
These tools are optional reference surfaces for math-first work. They are not
|
||||||
|
default repo dependencies. Add them to a local environment only when a task
|
||||||
|
needs an executable witness, conversion adapter, or independent solver.
|
||||||
|
|
||||||
|
The operating rule is simple: Lean remains the source of truth; these tools
|
||||||
|
produce receipts, counterexamples, fixtures, and sanity checks.
|
||||||
|
|
||||||
|
## Install Manifests
|
||||||
|
|
||||||
|
Python packages that are reasonable to install into a task-specific virtual
|
||||||
|
environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv venv .venv-science
|
||||||
|
source .venv-science/bin/activate
|
||||||
|
uv pip install -r requirements-optional-science.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Equivalent npm convenience commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run setup-science-light
|
||||||
|
npm run probe-science
|
||||||
|
```
|
||||||
|
|
||||||
|
Native command-line tools are listed in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
system-packages-optional-science.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not wire these into default CI unless the workflow is explicitly optional or
|
||||||
|
the tool is already installed on the runner.
|
||||||
|
|
||||||
|
## Probe What Is Available
|
||||||
|
|
||||||
|
Use the probe before asking an agent to rely on a domain tool:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 scripts/probe_science_toolbelt.py
|
||||||
|
python3 scripts/probe_science_toolbelt.py --json
|
||||||
|
python3 scripts/probe_science_toolbelt.py --json --out shared-data/artifacts/science_toolbelt/probe.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The probe exits successfully even when optional tools are missing. Missing tools
|
||||||
|
are data, not failure.
|
||||||
|
|
||||||
|
## Domain Priorities
|
||||||
|
|
||||||
|
| Domain | First tools | Use in this stack |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Genetics / bioinformatics | Biopython, pysam, samtools, bcftools, minimap2 | Validate FASTA/FASTQ/GenBank/SAM/BAM/VCF fixtures for the genetic-code, Hachimoji, and PIST surfaces. |
|
||||||
|
| CFD / PDE | Dedalus, ParaView | Produce spectral PDE reference traces for Burgers/KdV/hyperfluid claims without committing to a heavyweight engineering CFD stack. |
|
||||||
|
| Cryptography | liboqs-python, PyCryptodome, galois | Check post-quantum KEM/signature examples, hashes, finite-field arithmetic, and receipt digests. |
|
||||||
|
| Chemistry / materials | RDKit, Open Babel | Parse/canonicalize SMILES, compute descriptors, and turn molecular claims into inspectable fixtures. |
|
||||||
|
| Formal bridge | Z3, cvc5 | Search bounded counterexamples before spending Lean effort. |
|
||||||
|
| Algebra / graph theory | SageMath, GAP, NetworkX, Graphviz | Generate lattice/group/graph witnesses and diagrams for later Lean or receipt promotion. |
|
||||||
|
| Compression / signal | zstandard, PyWavelets | Provide compression baselines and spectral/wavelet witnesses for signal-shaping claims. |
|
||||||
|
|
||||||
|
## What Not To Do
|
||||||
|
|
||||||
|
- Do not add these packages to the default repo environment.
|
||||||
|
- Do not treat a solver result as a theorem.
|
||||||
|
- Do not commit generated datasets unless they are promoted as small,
|
||||||
|
receipt-bearing evidence.
|
||||||
|
- Do not copy implementation code from external tools into the repo.
|
||||||
|
|
||||||
|
## Receipt Pattern
|
||||||
|
|
||||||
|
For any adapter built on this toolbelt, prefer:
|
||||||
|
|
||||||
|
1. Input fixture path.
|
||||||
|
2. Tool name and version from `probe_science_toolbelt.py`.
|
||||||
|
3. Exact command or Python module call.
|
||||||
|
4. Output hash and short human-readable summary.
|
||||||
|
5. Link to the Lean theorem, claim registry entry, or distilled doc that the
|
||||||
|
receipt supports.
|
||||||
|
|
@ -5,7 +5,9 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"install-python": "uv python install 3.11.15",
|
"install-python": "uv python install 3.11.15",
|
||||||
"setup-cad-env": "cd 5-Applications/text-to-cad && python3.11 -m venv .venv && ./.venv/bin/pip install -r requirements-cad.txt",
|
"setup-cad-env": "cd 5-Applications/text-to-cad && python3.11 -m venv .venv && ./.venv/bin/pip install -r requirements-cad.txt",
|
||||||
"verify-cad": "cd 5-Applications/text-to-cad && ./.venv/bin/python -c \"import build123d; import OCP; print('CAD dependencies OK')\""
|
"verify-cad": "cd 5-Applications/text-to-cad && ./.venv/bin/python -c \"import build123d; import OCP; print('CAD dependencies OK')\"",
|
||||||
|
"setup-science-light": "uv venv .venv-science && . .venv-science/bin/activate && uv pip install -r requirements-optional-science.txt",
|
||||||
|
"probe-science": "python3 scripts/probe_science_toolbelt.py"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^12.4.1"
|
"better-sqlite3": "^12.4.1"
|
||||||
|
|
|
||||||
34
requirements-optional-science.txt
Normal file
34
requirements-optional-science.txt
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Optional science toolbelt for receipt-producing adapters.
|
||||||
|
#
|
||||||
|
# Install only when a task needs these domains:
|
||||||
|
#
|
||||||
|
# uv pip install -r requirements-optional-science.txt
|
||||||
|
#
|
||||||
|
# These packages are intentionally not part of the default repo setup. They
|
||||||
|
# provide reference implementations and data-format adapters for math-first
|
||||||
|
# verification receipts.
|
||||||
|
|
||||||
|
# Genetics / bioinformatics
|
||||||
|
biopython>=1.87
|
||||||
|
pysam>=0.24.0
|
||||||
|
|
||||||
|
# Chemistry / materials
|
||||||
|
rdkit>=2026.3.1
|
||||||
|
|
||||||
|
# SMT / formal-methods bridge
|
||||||
|
z3-solver>=4.16.0.0
|
||||||
|
cvc5>=1.3.4
|
||||||
|
|
||||||
|
# Cryptography / finite fields / symbolic checks
|
||||||
|
pycryptodome>=3.23.0
|
||||||
|
galois>=0.4.6
|
||||||
|
|
||||||
|
# Graphs, signal analysis, and compression baselines
|
||||||
|
networkx>=3.5
|
||||||
|
PyWavelets>=1.9.0
|
||||||
|
zstandard>=0.25.0
|
||||||
|
|
||||||
|
# Heavy or native-stack options. Keep commented unless a task explicitly needs
|
||||||
|
# the solver and the host has the native prerequisites.
|
||||||
|
# dedalus>=3.0.5
|
||||||
|
# liboqs-python>=0.14.1
|
||||||
242
scripts/probe_science_toolbelt.py
Executable file
242
scripts/probe_science_toolbelt.py
Executable file
|
|
@ -0,0 +1,242 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Probe optional science tools without requiring them.
|
||||||
|
|
||||||
|
The goal is not to make these tools part of the default stack. The goal is to
|
||||||
|
let agents and CI-adjacent smoke checks discover which reference solvers,
|
||||||
|
format adapters, and verification backends are available on the current host.
|
||||||
|
|
||||||
|
Exit code:
|
||||||
|
0 probe completed; missing optional tools are reported in the payload.
|
||||||
|
2 invalid CLI arguments or unable to write output.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import importlib
|
||||||
|
import json
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from dataclasses import asdict, dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class PythonTool:
|
||||||
|
key: str
|
||||||
|
domain: str
|
||||||
|
module: str
|
||||||
|
purpose: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class CommandTool:
|
||||||
|
key: str
|
||||||
|
domain: str
|
||||||
|
command: str
|
||||||
|
purpose: str
|
||||||
|
version_args: tuple[str, ...] = ("--version",)
|
||||||
|
|
||||||
|
|
||||||
|
PYTHON_TOOLS: tuple[PythonTool, ...] = (
|
||||||
|
PythonTool(
|
||||||
|
"biopython",
|
||||||
|
"genetics",
|
||||||
|
"Bio",
|
||||||
|
"FASTA/FASTQ/GenBank parsing and sequence manipulation",
|
||||||
|
),
|
||||||
|
PythonTool("pysam", "genetics", "pysam", "SAM/BAM/CRAM/VCF access from Python"),
|
||||||
|
PythonTool(
|
||||||
|
"rdkit",
|
||||||
|
"chemistry",
|
||||||
|
"rdkit",
|
||||||
|
"SMILES parsing, canonicalization, descriptors, fingerprints",
|
||||||
|
),
|
||||||
|
PythonTool("z3-solver", "formal-methods", "z3", "SMT checks before Lean proof work"),
|
||||||
|
PythonTool("cvc5", "formal-methods", "cvc5", "SMT checks and model finding"),
|
||||||
|
PythonTool(
|
||||||
|
"pycryptodome",
|
||||||
|
"cryptography",
|
||||||
|
"Crypto",
|
||||||
|
"hash/signature/cipher reference primitives",
|
||||||
|
),
|
||||||
|
PythonTool("galois", "cryptography", "galois", "finite-field arithmetic"),
|
||||||
|
PythonTool(
|
||||||
|
"networkx",
|
||||||
|
"graph-theory",
|
||||||
|
"networkx",
|
||||||
|
"graph certificates and topology receipts",
|
||||||
|
),
|
||||||
|
PythonTool(
|
||||||
|
"pywavelets",
|
||||||
|
"signal-processing",
|
||||||
|
"pywt",
|
||||||
|
"wavelet decompositions for spectral receipts",
|
||||||
|
),
|
||||||
|
PythonTool(
|
||||||
|
"zstandard",
|
||||||
|
"compression",
|
||||||
|
"zstandard",
|
||||||
|
"zstd baseline and dictionary-training adapter",
|
||||||
|
),
|
||||||
|
PythonTool("dedalus", "cfd-pde", "dedalus", "spectral PDE reference solver"),
|
||||||
|
PythonTool(
|
||||||
|
"liboqs-python",
|
||||||
|
"cryptography",
|
||||||
|
"oqs",
|
||||||
|
"Open Quantum Safe KEM/signature reference adapter",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
COMMAND_TOOLS: tuple[CommandTool, ...] = (
|
||||||
|
CommandTool(
|
||||||
|
"samtools",
|
||||||
|
"genetics",
|
||||||
|
"samtools",
|
||||||
|
"SAM/BAM/CRAM command-line verification",
|
||||||
|
),
|
||||||
|
CommandTool("bcftools", "genetics", "bcftools", "VCF/BCF command-line verification"),
|
||||||
|
CommandTool("minimap2", "genetics", "minimap2", "sequence alignment smoke checks"),
|
||||||
|
CommandTool(
|
||||||
|
"sage",
|
||||||
|
"algebra-crypto",
|
||||||
|
"sage",
|
||||||
|
"lattice, group, and symbolic mathematics",
|
||||||
|
("--version",),
|
||||||
|
),
|
||||||
|
CommandTool("gap", "algebra", "gap", "computational group-theory checks", ("--version",)),
|
||||||
|
CommandTool("z3", "formal-methods", "z3", "SMT solver CLI", ("--version",)),
|
||||||
|
CommandTool("cvc5", "formal-methods", "cvc5", "SMT solver CLI", ("--version",)),
|
||||||
|
CommandTool("zstd", "compression", "zstd", "compression baseline CLI", ("--version",)),
|
||||||
|
CommandTool("dot", "graph-theory", "dot", "Graphviz graph rendering for witness diagrams", ("-V",)),
|
||||||
|
CommandTool("obabel", "chemistry", "obabel", "Open Babel format conversion", ("-V",)),
|
||||||
|
CommandTool("paraview", "cfd-pde", "paraview", "CFD/PDE visualization frontend", ("--version",)),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _module_version(module: Any) -> str | None:
|
||||||
|
for attr in ("__version__", "VERSION", "version"):
|
||||||
|
value = getattr(module, attr, None)
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
if callable(value):
|
||||||
|
try:
|
||||||
|
value = value()
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
return str(value)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _probe_python(tool: PythonTool) -> dict[str, Any]:
|
||||||
|
try:
|
||||||
|
module = importlib.import_module(tool.module)
|
||||||
|
except Exception as exc:
|
||||||
|
return {
|
||||||
|
**asdict(tool),
|
||||||
|
"available": False,
|
||||||
|
"error": f"{type(exc).__name__}: {exc}",
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
**asdict(tool),
|
||||||
|
"available": True,
|
||||||
|
"version": _module_version(module),
|
||||||
|
"path": getattr(module, "__file__", None),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _run_version(path: str, args: tuple[str, ...]) -> str | None:
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
[path, *args],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=5,
|
||||||
|
check=False,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
text = (result.stdout or result.stderr).strip()
|
||||||
|
if not text:
|
||||||
|
return None
|
||||||
|
return text.splitlines()[0]
|
||||||
|
|
||||||
|
|
||||||
|
def _probe_command(tool: CommandTool) -> dict[str, Any]:
|
||||||
|
path = shutil.which(tool.command)
|
||||||
|
if path is None:
|
||||||
|
return {
|
||||||
|
**asdict(tool),
|
||||||
|
"available": False,
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
**asdict(tool),
|
||||||
|
"available": True,
|
||||||
|
"path": path,
|
||||||
|
"version": _run_version(path, tool.version_args),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_report() -> dict[str, Any]:
|
||||||
|
python_results = [_probe_python(tool) for tool in PYTHON_TOOLS]
|
||||||
|
command_results = [_probe_command(tool) for tool in COMMAND_TOOLS]
|
||||||
|
available = sum(1 for item in python_results + command_results if item["available"])
|
||||||
|
total = len(python_results) + len(command_results)
|
||||||
|
by_domain: dict[str, dict[str, int]] = {}
|
||||||
|
for item in python_results + command_results:
|
||||||
|
bucket = by_domain.setdefault(item["domain"], {"available": 0, "total": 0})
|
||||||
|
bucket["total"] += 1
|
||||||
|
if item["available"]:
|
||||||
|
bucket["available"] += 1
|
||||||
|
return {
|
||||||
|
"schema": "research_stack_optional_science_toolbelt_probe_v1",
|
||||||
|
"summary": {
|
||||||
|
"available": available,
|
||||||
|
"total": total,
|
||||||
|
"by_domain": by_domain,
|
||||||
|
},
|
||||||
|
"python": python_results,
|
||||||
|
"commands": command_results,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _print_text(report: dict[str, Any]) -> None:
|
||||||
|
summary = report["summary"]
|
||||||
|
print(f"optional science toolbelt: {summary['available']}/{summary['total']} available")
|
||||||
|
for section in ("python", "commands"):
|
||||||
|
print(f"\n{section}:")
|
||||||
|
for item in report[section]:
|
||||||
|
mark = "OK" if item["available"] else "--"
|
||||||
|
version = item.get("version")
|
||||||
|
suffix = f" ({version})" if version else ""
|
||||||
|
print(f" {mark} {item['key']}: {item['purpose']}{suffix}")
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str] | None = None) -> int:
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--json", action="store_true", help="emit JSON instead of text")
|
||||||
|
parser.add_argument("--out", type=Path, help="write the JSON report to this path")
|
||||||
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
|
report = build_report()
|
||||||
|
if args.out:
|
||||||
|
try:
|
||||||
|
args.out.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
args.out.write_text(
|
||||||
|
json.dumps(report, indent=2, sort_keys=True) + "\n",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
except OSError as exc:
|
||||||
|
print(f"error: failed to write {args.out}: {exc}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report, indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
_print_text(report)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
26
system-packages-optional-science.txt
Normal file
26
system-packages-optional-science.txt
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Optional system packages for science toolbelt adapters.
|
||||||
|
#
|
||||||
|
# These are command-line tools or heavyweight native stacks that Python
|
||||||
|
# requirements cannot reliably install. Names are Debian/Ubuntu-style package
|
||||||
|
# names where available; distro packages vary.
|
||||||
|
|
||||||
|
# Genetics / bioinformatics
|
||||||
|
samtools
|
||||||
|
bcftools
|
||||||
|
minimap2
|
||||||
|
|
||||||
|
# Formal methods / algebra
|
||||||
|
cvc5
|
||||||
|
z3
|
||||||
|
gap
|
||||||
|
sagemath
|
||||||
|
|
||||||
|
# Compression and receipt payload baselines
|
||||||
|
zstd
|
||||||
|
|
||||||
|
# Visualization / data inspection
|
||||||
|
graphviz
|
||||||
|
paraview
|
||||||
|
|
||||||
|
# Chemistry / materials native helpers
|
||||||
|
openbabel
|
||||||
Loading…
Add table
Reference in a new issue