Add a power operator

Done

Devanshi-cmd/devswarm-demo#3 · 2026-11-09 17:57:14 UTC · took 57.5s · Pull request

  1. Plan (done)
  2. Code (done)
  3. Test (done)
  4. Review (done)
  5. Finish (done)
Cost
$0.0077
Tests
Passed
Iterations
1
Re-plans
0
LLM calls
14
Prompt read from cache
67%

Usage by agent

Cost per agent
planner: $0.0013 planner planner, Cost: $0.0013 $0.0013 coder: $0.0027 coder coder, Cost: $0.0027 $0.0027 tester: $0.0025 tester tester, Cost: $0.0025 $0.0025 reviewer: $0.0012 reviewer reviewer, Cost: $0.0012 $0.0012
Tokens per agent
  • Cache read
  • Cache write
  • Input
  • Output
planner: 9,242 planner planner, Cache read: 4,329 planner, Cache write: 3,085 planner, Output: 1,820 9,242 coder: 32.6K coder coder, Cache read: 21.9K coder, Cache write: 7,674 coder, Output: 2,993 32.6K tester: 29.8K tester tester, Cache read: 18.8K tester, Cache write: 8,673 tester, Output: 2,373 29.8K reviewer: 11.3K reviewer reviewer, Cache read: 4,879 reviewer, Cache write: 5,536 reviewer, Output: 928 11.3K
View as table
AgentCostCache readCache writeInputOutput
planner$0.00134,3293,08581,820
coder$0.002721,8997,674122,993
tester$0.002518,7768,673102,373
reviewer$0.00124,8795,5366928

Timeline

  1. planner iteration 1 Finished 3 calls · 9,242 tokens · $0.0013 · 11.1s

    Loading…

  2. coder iteration 1 Finished 5 calls · 32.6K tokens · $0.0027 · 17.9s

    Loading…

  3. tester iteration 1 Finished 4 calls · 29.8K tokens · $0.0025 · 15.5s

    Loading…

  4. verify iteration 1 Passed 0.6s
    ....................                                                     [100%]
    20 passed in 0.07s
    
  5. reviewer iteration 1 Finished 2 calls · 11.3K tokens · $0.0012 · 6.3s

    Loading…

Final diff

diff --git a/README.md b/README.md
index 14ba480..1cf9d54 100644
--- a/README.md
+++ b/README.md
@@ -5,3 +5,5 @@ A tiny calculator with a known bug, used to demonstrate [DevSwarm](https://githu
 ```bash
 python calc.py 8 / 2
 ```
+
+Exponents use `^`, e.g. `python calc.py 2 ^ 3` prints `8.0`.
diff --git a/calc.py b/calc.py
index f16c6ca..5c9cde0 100644
--- a/calc.py
+++ b/calc.py
@@ -16,6 +16,16 @@ def calculate(left: float, operator: str, right: float) -> float:
         return left * right
     if operator == "/":
         return left / right
+    if operator == "^":
+        try:
+            result = left ** right
+        except ZeroDivisionError:
+            raise CalculatorError("0 cannot be raised to a negative power")
+        except OverflowError:
+            raise CalculatorError("result is too large")
+        if isinstance(result, complex):
+            raise CalculatorError("result is not a real number")
+        return result
     raise CalculatorError(f"unknown operator: {operator}")
 
 
diff --git a/test_calc.py b/test_calc.py
index 856b0c9..7dce994 100644
--- a/test_calc.py
+++ b/test_calc.py
@@ -4,7 +4,16 @@ from calc import CalculatorError, calculate, main
 
 @pytest.mark.parametrize(
     ("left", "operator", "right", "expected"),
-    [(2, "+", 3, 5), (5, "-", 3, 2), (2, "*", 3, 6), (8, "/", 2, 4)],
+    [
+        (2, "+", 3, 5),
+        (5, "-", 3, 2),
+        (2, "*", 3, 6),
+        (8, "/", 2, 4),
+        (2, "^", 3, 8),
+        (2, "^", 0, 1),
+        (9, "^", 0.5, 3.0),
+        (2, "^", -1, 0.5),
+    ],
 )
 def test_operations(left, operator, right, expected):
     assert calculate(left, operator, right) == expected
@@ -15,6 +24,21 @@ def test_unknown_operator():
         calculate(1, "%", 2)
 
 
+def test_power_zero_to_negative_power_raises():
+    with pytest.raises(CalculatorError):
+        calculate(0, "^", -1)
+
+
+def test_power_overflow_raises():
+    with pytest.raises(CalculatorError):
+        calculate(10.0, "^", 400.0)
+
+
+def test_power_negative_base_fractional_exponent_raises():
+    with pytest.raises(CalculatorError):
+        calculate(-8, "^", 1 / 3)
+
+
 def test_main_prints_result(capsys):
     assert main(["8", "/", "2"]) == 0
     assert capsys.readouterr().out.strip() == "4.0"
@@ -23,3 +47,46 @@ def test_main_prints_result(capsys):
 def test_main_reports_unknown_operator(capsys):
     assert main(["1", "%", "2"]) == 1
     assert "unknown operator" in capsys.readouterr().err
+
+
+def test_main_power(capsys):
+    assert main(["2", "^", "3"]) == 0
+    assert capsys.readouterr().out.strip() == "8.0"
+
+
+def test_main_reports_power_error(capsys):
+    assert main(["0", "^", "-1"]) == 1
+    assert "error:" in capsys.readouterr().err
+
+
+def test_main_power_overflow_reports_error(capsys):
+    assert main(["10", "^", "400"]) == 1
+    assert "error:" in capsys.readouterr().err
+
+
+def test_main_power_complex_result_reports_error(capsys):
+    assert main(["-8", "^", "0.5"]) == 1
+    captured = capsys.readouterr()
+    assert "error:" in captured.err
+    assert "j" not in captured.out
+
+
+def test_power_negative_base_integer_exponent_is_real():
+    assert calculate(-2, "^", 3) == -8
+
+
+def test_power_cli_subprocess_prints_8_0():
+    import subprocess
+    import sys
+    from pathlib import Path
+
+    script = Path(__file__).parent / "calc.py"
+    completed = subprocess.run(
+        [sys.executable, str(script), "2", "^", "3"],
+        capture_output=True,
+        text=True,
+        check=False,
+    )
+    assert completed.returncode == 0
+    assert completed.stdout.strip() == "8.0"
+    assert "Traceback" not in completed.stderr