27 KiB
SymClaw — Implementation Plan & Critical Analysis
Project: Open-Source Symbolic Computing for the Agentic Age
Codename: SymClaw
Stack: Rust Symbolic Engine + OpenClaw Agentic Bridge
Author: Omar (HPC-AI Platform)
Date: 2026-02-12
Status: Architecture Review
1. Strategic Assessment
1.1 What Makes This a Paradigm Shift
The roadmap you've drafted is strong, but to truly be paradigm-shifting, there are dimensions the original plan underweights. Here's what elevates this from "another CAS" to a genuine platform shift:
The Killer Insight: Deterministic Compute + Agentic Intelligence
Every existing CAS is either (a) deterministic but dumb (Mathematica, SymPy — you type exact commands) or (b) intelligent but unreliable (ChatGPT doing math — hallucinates). SymClaw is the first system where:
- The LLM handles intent ("what's the derivative of this messy physics equation?")
- The symbolic engine guarantees correctness (deterministic Rust computation)
- The e-graph finds the optimal form (not just an answer, but the best answer)
- The agentic layer delivers it anywhere (WhatsApp, Telegram, Canvas, voice)
This is the "compiler + IDE" moment for scientific computing. No one else is building this.
1.2 Critical Gaps in the Original Roadmap
| Gap | Why It Matters | Resolution |
|---|---|---|
| No numeric fallback strategy | Many real-world problems can't be solved symbolically | Add hybrid symbolic-numeric pipeline (Phase 2.5) |
| No error recovery / graceful degradation | Users will hit unsolvable expressions constantly | Implement "best effort" mode with confidence scoring |
| Parser underspecified | Input parsing is 50% of the user experience | Dedicate Sprint 1 to parser with extensive edge-case handling |
| No caching layer | Same expressions re-evaluated across sessions | Add expression-level memoization with LRU cache |
| Security model missing | Arbitrary expression evaluation is a DoS vector | Expression complexity limits, timeout enforcement, sandboxing |
| No migration path from existing tools | Scientists won't switch without import capability | SymPy/LaTeX import in V0.5, Mathematica notebook import in V1.0 |
| Collaboration undefined | Research is collaborative | Multi-user Canvas sessions via OpenClaw multi-agent routing (V1.0) |
| No offline mode | Scientists work on planes, in labs without internet | WASM module works fully offline; LLM intent parsing degrades to direct command mode |
1.3 Build vs. Integrate Decisions
Before writing a single line, these decisions save months:
| Component | Build | Integrate | Recommendation |
|---|---|---|---|
| Expression AST | ✅ | Build — core IP, must be Arc-based for your cluster | |
| Parser | ✅ | Build with nom — need custom notation support | |
| Simplifier | Hybrid | egg crate |
Integrate egg, build rule sets on top |
| Differentiation | ✅ | Build — well-defined algorithms, your rules | |
| Integration | ✅ | Build core; consider SymPy FFI for edge cases | |
| Linear Algebra | nalgebra |
Integrate nalgebra for numeric, build symbolic layer | |
| Plotting | Plotly.js | Integrate in Canvas; don't build a plotting library | |
| LaTeX rendering | KaTeX | Integrate — battle-tested, fast, WASM-compatible | |
| Arbitrary precision | num crate |
Integrate | |
| WASM compilation | wasm-bindgen |
Integrate |
2. Architecture Deep Dive
2.1 Expression AST — The Foundation
This is the most critical design decision. Get it wrong and everything downstream suffers.
// Core expression type — every operation in the system flows through this
#[derive(Clone, Hash, Eq, PartialEq, Debug)]
pub enum Expr {
// Atoms
Num(Rational), // Exact: 3/7, -42, 0
Float(OrderedFloat<f64>), // IEEE 754 when exact isn't needed
Symbol(Symbol), // Interned string: x, y, theta
Complex(Arc<Expr>, Arc<Expr>), // a + bi
// N-ary operations (flattened, canonically sorted)
Add(Vec<Arc<Expr>>), // a + b + c (not nested)
Mul(Vec<Arc<Expr>>), // a * b * c (not nested)
// Binary operations
Pow(Arc<Expr>, Arc<Expr>), // base^exponent
// Functions
Func(FuncId, Vec<Arc<Expr>>), // sin(x), log(x, base), custom(a, b, c)
// Calculus
Derivative(Arc<Expr>, Symbol, u32), // d^n f / dx^n
Integral(Arc<Expr>, Symbol, Option<Bounds>), // ∫f dx or ∫_a^b f dx
Limit(Arc<Expr>, Symbol, Arc<Expr>, Direction),
Sum(Arc<Expr>, Symbol, Arc<Expr>, Arc<Expr>), // Σ
Product(Arc<Expr>, Symbol, Arc<Expr>, Arc<Expr>), // Π
// Structural
Eq(Arc<Expr>, Arc<Expr>), // equation
Matrix(MatrixData), // symbolic matrix
Piecewise(Vec<(Arc<Expr>, Condition)>),
// Meta
Undefined, // 0/0, etc.
Infinity(Sign),
}
Critical Design Notes:
-
Arc, not Box — You need Send + Sync for rayon parallelism across your Pi cluster nodes. The ~8 bytes overhead per Arc is negligible vs. the threading flexibility.
-
Interned Symbols — Use the
string_internercrate. In a typical session, the same variable names (x, y, t, theta) appear thousands of times. Interning reduces memory and makes comparison O(1). -
Canonical Ordering —
Add(vec![x, 3])andAdd(vec![3, x])must be the same expression. Sort commutative operands by a canonical ordering (constants first, then symbols alphabetically, then complex expressions by depth). This is essential for e-graph efficiency. -
Flattened N-ary —
(a + b) + cbecomesAdd(vec![a, b, c]). This eliminates association ambiguity and makes pattern matching simpler.
2.2 The Egg Integration — This Is Your Moat
The equality saturation engine via egg is what differentiates SymClaw from SymPy. Here's why and how:
Why it matters:
Traditional CAS simplifiers apply rules greedily: pick a rule, apply it, repeat. This gets stuck in local optima. Example:
Input: (x^2 - 1) / (x - 1)
Greedy: tries to simplify numerator and denominator separately → stuck
Egg: discovers x^2 - 1 = (x+1)(x-1), cancels → (x+1) ✓
Egg explores ALL possible rewrites simultaneously using e-graphs, then extracts the simplest result. This is provably optimal (given enough rules and iterations).
Implementation strategy:
use egg::{*, rewrite as rw};
define_language! {
pub enum MathLang {
Num(i64),
"+" = Add([Id; 2]),
"*" = Mul([Id; 2]),
"/" = Div([Id; 2]),
"^" = Pow([Id; 2]),
"neg" = Neg([Id; 1]),
"sin" = Sin([Id; 1]),
"cos" = Cos([Id; 1]),
"ln" = Ln([Id; 1]),
"exp" = Exp([Id; 1]),
"d" = Deriv([Id; 2]), // d(expr, var)
Symbol(Symbol),
}
}
fn math_rules() -> Vec<Rewrite<MathLang, ConstantFold>> {
vec![
// Arithmetic identities
rw!("add-0"; "(+ ?a 0)" => "?a"),
rw!("mul-1"; "(* ?a 1)" => "?a"),
rw!("mul-0"; "(* ?a 0)" => "0"),
rw!("pow-0"; "(^ ?a 0)" => "1"),
rw!("pow-1"; "(^ ?a 1)" => "?a"),
// Commutativity
rw!("add-comm"; "(+ ?a ?b)" => "(+ ?b ?a)"),
rw!("mul-comm"; "(* ?a ?b)" => "(* ?b ?a)"),
// Associativity
rw!("add-assoc"; "(+ ?a (+ ?b ?c))" => "(+ (+ ?a ?b) ?c)"),
rw!("mul-assoc"; "(* ?a (* ?b ?c))" => "(* (* ?a ?b) ?c)"),
// Distribution
rw!("distribute"; "(* ?a (+ ?b ?c))" => "(+ (* ?a ?b) (* ?a ?c))"),
rw!("factor"; "(+ (* ?a ?b) (* ?a ?c))" => "(* ?a (+ ?b ?c))"),
// Differentiation rules (the magic — egg discovers derivatives)
rw!("d-const"; "(d ?c ?x)" => "0" if is_const("?c", "?x")),
rw!("d-var"; "(d ?x ?x)" => "1"),
rw!("d-add"; "(d (+ ?a ?b) ?x)" => "(+ (d ?a ?x) (d ?b ?x))"),
rw!("d-mul"; "(d (* ?a ?b) ?x)" =>
"(+ (* (d ?a ?x) ?b) (* ?a (d ?b ?x)))"),
rw!("d-pow"; "(d (^ ?a ?n) ?x)" =>
"(* (* ?n (^ ?a (+ ?n -1))) (d ?a ?x))"
if is_const("?n", "?x")),
rw!("d-sin"; "(d (sin ?a) ?x)" => "(* (cos ?a) (d ?a ?x))"),
rw!("d-cos"; "(d (cos ?a) ?x)" => "(* (neg (sin ?a)) (d ?a ?x))"),
rw!("d-exp"; "(d (exp ?a) ?x)" => "(* (exp ?a) (d ?a ?x))"),
rw!("d-ln"; "(d (ln ?a) ?x)" => "(* (/ 1 ?a) (d ?a ?x))"),
// Trig identities
rw!("sin2+cos2"; "(+ (^ (sin ?a) 2) (^ (cos ?a) 2))" => "1"),
rw!("exp-ln"; "(exp (ln ?a))" => "?a"),
rw!("ln-exp"; "(ln (exp ?a))" => "?a"),
]
}
Explain Mode — The "Show Your Work" Feature:
// Using egg's explain API to show step-by-step derivation
let runner = Runner::default()
.with_explanations_enabled()
.with_expr(&start)
.run(&rules);
let explanation = runner.explain_equivalence(&start, &goal);
// Returns: [(rule_name, before_expr, after_expr), ...]
// User sees: "Applied product rule → Applied power rule → Simplified"
This is huge for education. No other CAS can show WHY it simplified an expression.
2.3 OpenClaw Skill Architecture
┌─────────────────────────────────────────┐
│ User's Phone/Desktop │
│ Telegram │ WhatsApp │ Canvas │ WebChat │
└─────────────┬───────────────────────────┘
│ message: "derive sin(x^2)"
▼
┌─────────────────────────────────────────┐
│ OpenClaw Gateway (Node.js) │
│ ┌─────────────────────────────────┐ │
│ │ LLM (Claude/GPT) — Intent Parse │ │
│ │ "derive sin(x^2)" │ │
│ │ → tool: math_eval │ │
│ │ → expr: "d/dx(sin(x^2))" │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ┌──────────────▼──────────────────┐ │
│ │ symclaw Skill (JS wrapper) │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ Option A: WASM Module │ │ │
│ │ │ (in-process, fast) │ │ │
│ │ └────────────────────────┘ │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ Option B: Subprocess │ │ │
│ │ │ (native, full perf) │ │ │
│ │ └────────────────────────┘ │ │
│ └──────────────┬──────────────────┘ │
│ │ result + LaTeX │
│ ┌──────────────▼──────────────────┐ │
│ │ Response Formatter │ │
│ │ Telegram: ASCII + LaTeX image │ │
│ │ Canvas: Interactive HTML │ │
│ │ WhatsApp: ASCII + rendered PNG │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
2.4 Canvas Manipulate — Real-Time Math Exploration
This is the feature that makes scientists' eyes light up. Mathematica's Manipulate[] is one of its most beloved features. Here's how we replicate it:
// A2UI JSONL payload pushed to Canvas
{"surfaceUpdate": {
"surfaceId": "manipulate-1",
"components": [
{"id": "title", "component": {"Text": {
"text": {"literalString": "f(x) = a·sin(b·x + c)"},
"usageHint": "h2"
}}},
{"id": "slider-a", "component": {"Slider": {
"min": 0.1, "max": 5.0, "step": 0.1, "value": 1.0,
"label": "a (amplitude)"
}}},
{"id": "slider-b", "component": {"Slider": {
"min": 0.1, "max": 10.0, "step": 0.1, "value": 1.0,
"label": "b (frequency)"
}}},
{"id": "slider-c", "component": {"Slider": {
"min": -3.14, "max": 3.14, "step": 0.01, "value": 0.0,
"label": "c (phase)"
}}},
{"id": "plot", "component": {"WebView": {
"html": "<canvas id='plot'></canvas><script>/* Plotly + WASM eval */</script>"
}}}
]
}}
The magic: slider changes trigger WASM evaluation directly in the Canvas JavaScript, no round-trip to the server needed. 30fps updates on a phone.
3. Testing Strategy — Correctness Is Non-Negotiable
3.1 The Testing Pyramid
╱╲
╱ ╲ Manual Testing
╱ 5% ╲ (demo to researchers, get feedback)
╱──────╲
╱ ╲ Stress/Load Tests
╱ 10% ╲ (Pi cluster, WASM limits, DoS)
╱────────────╲
╱ ╲ Integration Tests
╱ 15% ╲ (OpenClaw → Engine → Canvas pipeline)
╱──────────────────╲
╱ ╲ Property-Based Tests
╱ 25% ╲ (proptest: numerical invariants)
╱────────────────────────╲
╱ ╲ Unit Tests
╱ 45% ╲ (every rule, every function)
╱──────────────────────────────╲
3.2 Property-Based Testing (The Secret Weapon)
use proptest::prelude::*;
// Strategy: generate random mathematical expressions
fn arb_expr(depth: u32) -> impl Strategy<Value = Expr> {
let leaf = prop_oneof![
(1..100i64).prop_map(|n| Expr::Num(Rational::from(n))),
Just(Expr::Symbol("x".into())),
Just(Expr::Symbol("y".into())),
];
leaf.prop_recursive(depth, 256, 10, |inner| {
prop_oneof![
(inner.clone(), inner.clone()).prop_map(|(a, b)|
Expr::Add(vec![Arc::new(a), Arc::new(b)])),
(inner.clone(), inner.clone()).prop_map(|(a, b)|
Expr::Mul(vec![Arc::new(a), Arc::new(b)])),
inner.clone().prop_map(|a|
Expr::Func(FuncId::Sin, vec![Arc::new(a)])),
]
})
}
proptest! {
// INVARIANT 1: Simplification preserves numerical value
#[test]
fn simplify_preserves_value(
expr in arb_expr(4),
x in -10.0f64..10.0,
) {
let original = expr.eval(&[("x", x)]);
let simplified = simplify(&expr);
let result = simplified.eval(&[("x", x)]);
if original.is_finite() && result.is_finite() {
prop_assert!((original - result).abs() < 1e-10,
"Simplification changed value: {} → {}", original, result);
}
}
// INVARIANT 2: Simplification is idempotent
#[test]
fn simplify_idempotent(expr in arb_expr(3)) {
let once = simplify(&expr);
let twice = simplify(&once);
prop_assert_eq!(once, twice, "Not idempotent");
}
// INVARIANT 3: Parse round-trip
#[test]
fn parse_roundtrip(expr in arb_expr(3)) {
let printed = format!("{}", expr);
let reparsed = parse(&printed).unwrap();
prop_assert_eq!(expr, reparsed, "Round-trip failed");
}
// INVARIANT 4: Derivative + Integral approximate inverse
#[test]
fn derivative_integral_roundtrip(
expr in arb_polynomial(3), // restrict to polynomials for tractability
x in -5.0f64..5.0,
) {
let d = differentiate(&expr, "x");
let i = integrate(&d, "x");
let diff = (expr.eval(&[("x", x)]) - i.eval(&[("x", x)])).abs();
// Should differ by at most a constant
let diff2 = (expr.eval(&[("x", x + 0.1)]) - i.eval(&[("x", x + 0.1)])).abs();
prop_assert!((diff - diff2).abs() < 1e-8,
"Integral of derivative should differ by constant");
}
}
3.3 Integration Test: Full Pipeline
// test/integration/telegram-to-canvas.test.ts
describe('Telegram → Engine → Canvas pipeline', () => {
it('should differentiate and render on Canvas', async () => {
// 1. Simulate Telegram message
const response = await gateway.handleMessage({
channel: 'telegram',
sender: '+15555551234',
text: 'What is the derivative of x^3 * sin(x)?'
});
// 2. Verify text response
expect(response.text).toContain('3x²·sin(x) + x³·cos(x)');
// 3. Verify LaTeX image was generated
expect(response.attachments).toHaveLength(1);
expect(response.attachments[0].mimeType).toBe('image/png');
// 4. Verify Canvas push (if mobile node connected)
const canvasPush = await gateway.getLastCanvasPush();
expect(canvasPush.surfaceId).toBe('math-result');
expect(canvasPush.components).toContainEqual(
expect.objectContaining({ id: 'latex-display' })
);
});
});
3.4 Stress Test: Pi Cluster
#!/bin/bash
# stress_test.sh — Run on Pi cluster control node
# Generate 1000 random expressions and fire them concurrently
for i in $(seq 1 1000); do
EXPR=$(symclaw-cli random-expr --depth 5 --seed $i)
curl -s -X POST http://gateway:18789/api/eval \
-H "Content-Type: application/json" \
-d "{\"expr\": \"$EXPR\"}" &
# Rate limit: 50 concurrent
[ $(jobs -r | wc -l) -ge 50 ] && wait -n
done
wait
echo "All 1000 evaluations complete"
# Verify: no crashes, no OOM, all returned valid results
4. Deployment Architecture
4.1 Single-Node (90% of users)
# docker-compose.yml — one command: docker compose up
version: '3.8'
services:
symclaw:
image: ghcr.io/symclaw/symclaw:latest
ports:
- "18789:18789" # OpenClaw Gateway
- "3000:3000" # WebChat
volumes:
- ~/.openclaw:/root/.openclaw
- ~/.symclaw:/root/.symclaw
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- SYMCLAW_ENGINE=wasm # or 'native' for full performance
restart: unless-stopped
deploy:
resources:
limits:
memory: 2G
4.2 Pi Cluster (Power Users)
┌──────────────────────────────────────────┐
│ Pi 5 (Control Node) │
│ OpenClaw Gateway + Tailscale │
│ Load Balancer (round-robin) │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Pi 4 #1│ │ Pi 4 #2│ │ Pi 4 #3│ │
│ │ Engine │ │ Engine │ │ Engine │ │
│ │ Worker │ │ Worker │ │ Worker │ │
│ └────────┘ └────────┘ └────────┘ │
│ ↕ Tailscale mesh ↕ │
│ ┌──────────────────────────────┐ │
│ │ x86 Workstation (optional) │ │
│ │ RTX 5090 — heavy compute │ │
│ └──────────────────────────────┘ │
└──────────────────────────────────────────┘
4.3 Nix Deployment
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
crane.url = "github:ipetkov/crane";
};
outputs = { self, nixpkgs, rust-overlay, crane, ... }:
let
systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
in {
packages = builtins.listToAttrs (map (system: {
name = system;
value = {
symclaw-core = crane.lib.${system}.buildPackage {
src = ./core;
# Cross-compile for Pi from x86
};
symclaw-wasm = crane.lib.${system}.buildPackage {
src = ./wasm;
CARGO_BUILD_TARGET = "wasm32-unknown-unknown";
};
};
}) systems);
nixosModules.symclaw = { config, ... }: {
services.symclaw = {
enable = true;
port = 18789;
engineMode = "native"; # or "wasm"
anthropicApiKey = config.sops.secrets.anthropic.path;
};
};
};
}
5. Open Source & Community Strategy
5.1 Launch Sequence
| Week | Action | Channel |
|---|---|---|
| T-2 | Soft launch: share with 10 trusted alpha testers | Direct invite |
| T-1 | Blog post: "Why We Built an Open-Source Mathematica in Rust" | Personal blog + dev.to |
| T+0 | GitHub public + crates.io publish | GitHub |
| T+0 | Hacker News "Show HN" post | Hacker News |
| T+0 | r/rust, r/math, r/opensource posts | |
| T+1 | OpenClaw Discord announcement | OpenClaw community |
| T+2 | Video demo: "From Telegram to LaTeX in 2 Seconds" | YouTube + X |
| T+4 | Reach out to university math departments | Email + academic networks |
5.2 Good First Issues (Pre-Labeled)
- "Add hyperbolic trig functions (sinh, cosh, tanh)"
- "Implement pretty-print for matrix expressions"
- "Add LaTeX input parser (basic subset)"
- "Write property test for trig identities"
- "Add Fibonacci sequence to the series module"
- "Improve error messages for parse failures"
- "Add --json output flag to CLI"
5.3 Governance
- License: MIT + Apache 2.0 (dual license, standard Rust ecosystem)
- Contributions: All PRs require 1 review + CI green + property tests pass
- Rule contributions: New rewrite rules require (a) correctness proof sketch, (b) proptest coverage, (c) benchmark showing no performance regression
- Breaking changes: Semantic versioning, deprecation warnings in minor versions
6. What the Roadmap Was Missing — Additions
6.1 Caching Layer (Add to Phase 1)
use lru::LruCache;
use std::sync::Mutex;
// Expression-level memoization
lazy_static! {
static ref SIMPLIFY_CACHE: Mutex<LruCache<u64, Arc<Expr>>> =
Mutex::new(LruCache::new(NonZeroUsize::new(10_000).unwrap()));
}
pub fn simplify_cached(expr: &Expr) -> Arc<Expr> {
let hash = expr.stable_hash();
if let Some(cached) = SIMPLIFY_CACHE.lock().unwrap().get(&hash) {
return cached.clone();
}
let result = simplify(expr);
SIMPLIFY_CACHE.lock().unwrap().put(hash, result.clone());
result
}
6.2 Confidence Scoring (Add to Phase 2)
Not all simplifications are equally trustworthy. Add a confidence score:
pub struct EvalResult {
pub expr: Expr,
pub latex: String,
pub confidence: Confidence,
pub steps: Vec<Step>,
}
pub enum Confidence {
Exact, // Algebraic simplification, fully verified
HighConfidence, // Integration by standard method
Heuristic, // Pattern-matched, not formally verified
NumericOnly, // Could not solve symbolically, numeric result
Failed(String), // Could not compute, here's why
}
6.3 Offline Mode (Add to Phase 3)
When no LLM is available (no API key, no internet), SymClaw should still work:
User types: /math d/dx(x^2 * sin(x))
→ Direct command parsing (no LLM needed)
→ Engine computes result
→ Returns ASCII: 2x*sin(x) + x^2*cos(x)
User types: "what's the derivative of x squared times sine x"
→ No LLM available
→ Respond: "Natural language mode requires an AI model connection.
Use command syntax: /derive x^2 * sin(x)"
6.4 Benchmark Suite (Add to Phase 5)
Compare against SymPy on standardized problems:
// benchmarks/sympy_parity.rs
const BENCHMARK_PROBLEMS: &[(&str, &str)] = &[
("simplify", "(x^2 - 1)/(x - 1)", "x + 1"),
("derive", "d/dx(x^3 * sin(x))", "3*x^2*sin(x) + x^3*cos(x)"),
("integrate", "∫ x*exp(x) dx", "x*exp(x) - exp(x)"),
("solve", "x^2 - 5*x + 6 = 0", "{2, 3}"),
("taylor", "sin(x) about 0 order 5", "x - x^3/6 + x^5/120"),
("limit", "lim(x→0) sin(x)/x", "1"),
// ... 100+ problems from MIT OCW
];
6.5 Telemetry & Observability (Add to Phase 4)
// Prometheus metrics exposed at /metrics
pub struct EngineMetrics {
pub eval_latency: Histogram, // How long evaluations take
pub egraph_size: Gauge, // Current e-graph node count
pub cache_hit_rate: Counter, // Memoization effectiveness
pub parse_errors: Counter, // Input quality signal
pub timeout_count: Counter, // Expressions that hit limits
pub active_sessions: Gauge, // Connected OpenClaw sessions
}
Surface these in Omar's OpenClaw Mission Control Dashboard.
7. Timeline Summary
Week 1-2: Phase 0 — Foundation (CI/CD, Nix, project scaffolding)
Week 3-6: Phase 1 — Engine Core: Arithmetic, Algebra, Egg, CLI
Week 7-10: Phase 2 — Engine Core: Calculus, Solving, Series, WASM
Week 11-13: Phase 3 — OpenClaw Skill, Canvas, Manipulate
Week 14-15: Phase 4 — Docker, Nix, Pi Cluster, Tailscale
Week 16-18: Phase 5 — Testing, Docs, Community, V0.1 Alpha Release
─────────────────────────────────────────────────────────────────
Week 19-30: Phase 6 — V0.5 Beta (LinAlg, ODEs, Jupyter)
Week 31-44: Phase 7 — V1.0 Launch (GPU, Clawbernetes, Collaboration)
Total to Alpha: ~18 weeks
Total to Production Launch: ~44 weeks
8. Final Recommendation
This project is viable and genuinely differentiated. The combination of:
- Rust performance (10-100x over Python CAS)
- Equality saturation (provably optimal simplification)
- Agentic AI delivery (message your math assistant on WhatsApp)
- Edge deployment (Pi cluster, WASM, offline-capable)
- Open source (MIT, community-driven)
...creates a product that doesn't exist today. The closest comparison is if Wolfram built Mathematica on top of ChatGPT and gave it away for free — except you own the infrastructure.
Key risk to manage: Scope. Mathematica has 6,600 functions built over 35 years. SymClaw needs to ship V0.1 with ~50 functions that cover 80% of undergraduate math, then let the community build the rest. The architecture (extensible rule sets, community ClawHub skills) makes this feasible.
The paradigm shift isn't the math engine — it's the delivery model. Scientists don't want another desktop app. They want to text their math assistant at 2am from bed and get a correct, beautifully rendered answer on their phone. That's what SymClaw delivers.