artifacts: add calculators/ — the 30 built calculators (5/variant) + machine-docs + git logs

This commit is contained in:
2026-06-16 15:39:42 +00:00
parent 64bc360fc0
commit bb85aa9f11
728 changed files with 34148 additions and 0 deletions

View File

@ -0,0 +1,9 @@
# BACKLOG-eval.md
## Build backlog
All items complete. Gates D1D5 claimed.
## Adversary findings
(none yet)

View File

@ -0,0 +1,14 @@
# BACKLOG-lex.md
## Build backlog
- [x] D1 — Numbers: integers and floats tokenize correctly
- [x] D2 — Operators & parens: all six symbols tokenize correctly
- [x] D3 — Whitespace skipped; invalid chars raise LexError
- [x] D4 — 20 unit tests passing under python -m unittest
All items complete. Awaiting Adversary PASS verdicts.
## Adversary findings
_(Adversary writes here)_

View File

@ -0,0 +1,16 @@
# BACKLOG-parse.md — Phase `parse`
## Build backlog
- [x] Write calc/parser.py (ParseError, Num, BinOp, Unary, parse())
- [x] Write calc/test_parser.py (unittest, D1-D5 coverage)
- [x] Claim D1 (precedence)
- [x] Claim D2 (left associativity)
- [x] Claim D3 (parentheses)
- [x] Claim D4 (unary minus)
- [x] Claim D5 (errors)
- [x] Claim D6 (tests green)
- [ ] Await Adversary verdict on D1D6
## Adversary findings
*(None yet — awaiting gate claims)*

View File

@ -0,0 +1,5 @@
# DECISIONS.md — Shared (append-only)
## 2026-06-15T04:30:28Z — Adversary initialized
Adversary loop started for phase `lex`. No decisions yet.

View File

@ -0,0 +1,35 @@
# JOURNAL-eval.md
## Session 1
### Implementation
Created three files:
- `calc/evaluator.py``evaluate(node)` walks Num/BinOp/Unary nodes. Division uses Python `/` (true division). After division, normalizes whole-valued floats to int via `int(result)`.
- `calc/test_evaluator.py` — 16 tests covering D1 arithmetic (all 5 DoD cases + extras), D2 division/EvalError, D3 type normalization.
- `calc.py` — CLI: parses argv[1], calls tokenize→parse→evaluate, prints result; catches LexError/ParseError/EvalError, prints to stderr, exits 1.
### Verification run
```
$ python -m unittest -q
Ran 65 tests in 0.001s
OK
$ python calc.py "2+3*4"
14
$ python calc.py "(2+3)*4"
20
$ python calc.py "7/2"
3.5
$ python calc.py "4/2"
2
$ python calc.py "1/0" 2>&1; echo "exit: $?"
error: division by zero
exit: 1
$ python calc.py "1 +" 2>&1; echo "exit: $?"
error: unexpected end of input
exit: 1
```
All outputs match DoD specs. 65 tests (lex + parse + eval) pass, zero failures.

View File

@ -0,0 +1,41 @@
# JOURNAL-lex.md — Adversary Journal
## 2026-06-15T04:30:28Z — Initialized
Adversary started. Phase plan read. No Builder work present yet.
Watching for gate claims in machine-docs/STATUS-lex.md.
---
# JOURNAL-lex.md — Builder Entries
## 2026-06-15 — Implementation complete
Built `calc/lexer.py` and `calc/test_lexer.py` in a single session.
**Design choices:**
- `Token` uses `__slots__` for memory efficiency; `__eq__` for test assertions.
- Number parsing: scan ahead consuming digits and at most one `.`. A leading dot (`.5`) and trailing dot (`10.`) both work because the while loop checks `src[j] == "."` only when `not has_dot`.
- Integer values stored as `int`, floats as `float` — allows parser to distinguish.
- `LexError` extends `Exception` directly; message includes the character repr and its position.
**Test run:**
```
$ python -m unittest -q
....................
----------------------------------------------------------------------
Ran 20 tests in 0.000s
OK
```
**Verification commands run locally:**
```
$ python -c "from calc.lexer import tokenize; print([(t.kind,t.value) for t in tokenize('3.5*(1-2)')])"
[('NUMBER', 3.5), ('STAR', '*'), ('LPAREN', '('), ('NUMBER', 1), ('MINUS', '-'), ('NUMBER', 2), ('RPAREN', ')'), ('EOF', None)]
$ python -c "from calc.lexer import tokenize; tokenize('1 @ 2')"
Traceback:
...
calc.lexer.LexError: unexpected character '@' at position 2
```

View File

@ -0,0 +1,32 @@
# JOURNAL-parse.md
## 2026-06-15 — Build + verify
Lex phase DONE. Token kinds: NUMBER, PLUS, MINUS, STAR, SLASH, LPAREN, RPAREN, EOF.
Grammar chosen (iterative at each level → left associativity by construction):
```
expr → term (('+' | '-') term)*
term → unary (('*' | '/') unary)*
unary → '-' unary | primary
primary → NUMBER | '(' expr ')'
```
### Manual verification output
```
D1 1+2*3: BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))
D2 8-3-2: BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))
D2 8/4/2: BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))
D3 (1+2)*3: BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))
D4 -5: Unary('-', Num(5))
D4 -(1+2): Unary('-', BinOp('+', Num(1), Num(2)))
D4 3*-2: BinOp('*', Num(3), Unary('-', Num(2)))
D5 '1 +' -> ParseError: unexpected end of input
D5 '(1' -> ParseError: unclosed parenthesis
D5 '1 2' -> ParseError: unexpected token 'NUMBER' (2) after expression
D5 ')(' -> ParseError: unexpected token 'RPAREN' (')')
D5 '' -> ParseError: empty input
```
Test run: `Ran 48 tests in 0.001s — OK` (21 lex + 27 parser)

View File

@ -0,0 +1,60 @@
# REVIEW-eval.md — Adversary verdicts
## eval/D1: PASS @2026-06-15T04:45:33Z
**Evidence (cold run, commit 3b507ee):**
```
2+3*4 → 14 ✓
(2+3)*4 → 20 ✓
8-3-2 → 3 ✓
-2+5 → 3 ✓
2*-3 → -6 ✓
```
Extra probes: `--5`→5, `-(3+4)`→-7, `1+2+3+4+5`→15 ✓
---
## eval/D2: PASS @2026-06-15T04:45:33Z
**Evidence:**
- `7/2``3.5` (true division, not integer) ✓
- `1/0``EvalError: division by zero` (not bare ZeroDivisionError) ✓
- `5/(2-2)``EvalError`
---
## eval/D3: PASS @2026-06-15T04:45:33Z
**Evidence:**
```
4/2 → int 2 ✓
7/2 → float 3.5 ✓
3*2 → int 6 ✓
-4/2 → int -2 ✓
1/3 → float 0.333... ✓
2.5*2 → int 5 ✓
```
---
## eval/D4: PASS @2026-06-15T04:45:33Z
**Evidence:**
```
python calc.py "2+3*4" → stdout: 14, exit 0 ✓
python calc.py "1/0" → stderr: "error: division by zero", exit 1, empty stdout ✓
python calc.py "1 +" → stderr: "error: unexpected end of input", exit 1 ✓
python calc.py → exit 1 (usage error) ✓
python calc.py "1+1" "extra" → exit 1 (too many args) ✓
```
---
## eval/D5: PASS @2026-06-15T04:45:33Z
**Evidence:**
```
Ran 65 tests in 0.001s OK (21 lex + 27 parser + 17 evaluator) ✓
```
- `test_evaluator.py` covers D1 (arithmetic), D2 (division/EvalError), D3 (result type) ✓
- No regressions in lex or parse suites ✓

View File

@ -0,0 +1,69 @@
# REVIEW-lex.md — Adversary Verdicts
## Gates
- D1: PASS @2026-06-15T04:34:35Z
- D2: PASS @2026-06-15T04:34:35Z
- D3: PASS @2026-06-15T04:40:18Z (re-verified after AF-1 fix)
- D4: PASS @2026-06-15T04:40:18Z (21 tests, 0 failures)
All DoD items verified. VETO lifted.
---
## D1 — Numbers: PASS @2026-06-15T04:34:35Z
```
NUMBER 42 int ✓
NUMBER 3.14 float ✓
NUMBER 0.5 ✓ (.5 leading dot)
NUMBER 10.0 float ✓ (10. trailing dot)
[('NUMBER', 42), ('EOF', None)] ✓
```
---
## D2 — Operators & Parens: PASS @2026-06-15T04:34:35Z
```
['NUMBER', 'PLUS', 'NUMBER', 'STAR', 'NUMBER', 'EOF'] ✓ (1+2*3)
[('PLUS', '+'), ('MINUS', '-'), ('STAR', '*'), ('SLASH', '/'), ('LPAREN', '('), ('RPAREN', ')'), ('EOF', None)] ✓
```
---
## D3 — Whitespace & Errors: PASS @2026-06-15T04:40:18Z
**First verdict (FAIL @2026-06-15T04:34:35Z):** bare `.` raised `ValueError` not `LexError` (AF-1).
**Re-verified after fix commit f40a364:**
```
Ran 21 tests in 0.000s — OK ✓
['NUMBER', 'PLUS', 'NUMBER', 'EOF'] (whitespace skipped) ✓
tokenize('.') → LexError: invalid number literal '.' at position 0 ✓
tokenize('1 @ 2') → LexError: unexpected character '@' at position 2 ✓
```
Valid floats unaffected by fix: `.5``0.5`, `10.``10.0`, `3.5*(1-2)` correct.
---
## D4 — Tests Green: PASS @2026-06-15T04:40:18Z
```
Ran 21 tests in 0.000s
OK
```
21 tests (was 20; `test_bare_dot_raises_lex_error` added). All three required DoD examples covered and passing.
---
## Adversary findings
### AF-1 (CLOSED @2026-06-15T04:40:18Z): Bare `.` leaked `ValueError` instead of `LexError`
**Fix:** `lexer.py` now wraps `float(raw)` / `int(raw)` in try/except, re-raises as `LexError`. Test added.
Re-tested: `tokenize('.')` now raises `LexError: invalid number literal '.' at position 0`. ✓
_Closed by Adversary after re-test._

View File

@ -0,0 +1,67 @@
# REVIEW-parse.md — Adversary verdicts for phase `parse`
Phase plan SSOT: /home/loops/project-orchestrator/projects/agent-orchestrator-benchmark/plans/calc/parse.md
Gates: D1 (precedence), D2 (left associativity), D3 (parentheses), D4 (unary minus), D5 (errors), D6 (tests green)
## Verdicts
- D1: PASS @2026-06-15T04:41:47Z
- D2: PASS @2026-06-15T04:41:47Z
- D3: PASS @2026-06-15T04:41:47Z
- D4: PASS @2026-06-15T04:41:47Z
- D5: PASS @2026-06-15T04:41:47Z
- D6: PASS @2026-06-15T04:41:47Z
All DoD gates PASS. No VETO. Phase `parse` complete — Builder may write ## DONE to STATUS-parse.md.
---
## Evidence
**D1 — Precedence**
```
1+2*3 → BinOp('+', Num(1), BinOp('*', Num(2), Num(3))) ✓ (* binds tighter)
2*3+4 → BinOp('+', BinOp('*', Num(2), Num(3)), Num(4)) ✓
1+2*3-4/2 → BinOp('-', BinOp('+', Num(1), BinOp('*', Num(2), Num(3))), BinOp('/', Num(4), Num(2))) ✓
```
**D2 — Left Associativity**
```
8-3-2 → BinOp('-', BinOp('-', Num(8), Num(3)), Num(2)) ✓
8/4/2 → BinOp('/', BinOp('/', Num(8), Num(4)), Num(2)) ✓
1-2+3 → BinOp('+', BinOp('-', Num(1), Num(2)), Num(3)) ✓
2/3*4 → BinOp('*', BinOp('/', Num(2), Num(3)), Num(4)) ✓
```
**D3 — Parentheses**
```
(1+2)*3 → BinOp('*', BinOp('+', Num(1), Num(2)), Num(3)) ✓
((((1)))) → Num(1) ✓
```
**D4 — Unary Minus**
```
-5 → Unary('-', Num(5)) ✓
-(1+2) → Unary('-', BinOp('+', Num(1), Num(2))) ✓
3 * -2 → BinOp('*', Num(3), Unary('-', Num(2))) ✓
--5 → Unary('-', Unary('-', Num(5))) ✓
-2*3 → BinOp('*', Unary('-', Num(2)), Num(3)) ✓
2+-3 → BinOp('+', Num(2), Unary('-', Num(3))) ✓
-2*-3 → BinOp('*', Unary('-', Num(2)), Unary('-', Num(3))) ✓
```
**D5 — Errors (all raise ParseError, no wrong exception types)**
```
'1 +' → ParseError: unexpected end of input ✓
'(1' → ParseError: unclosed parenthesis ✓
'1 2' → ParseError: unexpected token 'NUMBER'… ✓
')(' → ParseError: unexpected token 'RPAREN' ✓
'' → ParseError: empty input ✓
Extra probes: '+1', '1++2', '1*', '((1+2)', '1+2)', '*', '()', '1 + + 2' — all ParseError ✓
```
**D6 — Tests Green**
```
Ran 48 tests in 0.001s OK (21 lex + 27 parser) ✓
```

View File

@ -0,0 +1,46 @@
# STATUS-eval.md
## DONE
All eval gates D1D5 Adversary-verified PASS. Phase complete.
---
## Gate: D1-D5 CLAIMED → ALL PASS
All gates are implemented and self-verified. Claiming D1D5 together.
### WHAT is claimed
- D1 — arithmetic: evaluate() correct for +, -, *, /, precedence, parens, unary minus
- D2 — division: true division, EvalError on divide-by-zero (no bare ZeroDivisionError)
- D3 — result type: whole-valued → int, non-whole → float
- D4 — CLI: `python calc.py <expr>` prints result and exits 0; errors to stderr, non-zero exit
- D5 — tests green + no regression
### HOW to verify (cold, from fresh clone)
```bash
cd <repo-root>
python -m unittest -q # must be 0 failures (65 tests)
python calc.py "2+3*4" # expect: 14
python calc.py "(2+3)*4" # expect: 20
python calc.py "7/2" # expect: 3.5
python calc.py "4/2" # expect: 2
python calc.py "1/0" # expect: non-zero exit, error on stderr
python calc.py "1 +" # expect: non-zero exit, error on stderr
```
### EXPECTED outcomes
- unittest: `Ran 65 tests in ~0.001s``OK`
- `2+3*4``14`
- `(2+3)*4``20`
- `7/2``3.5`
- `4/2``2`
- `1/0` → exit 1, stderr: `error: division by zero`
- `1 +` → exit 1, stderr: `error: unexpected end of input`
### WHERE inputs live
- `calc/evaluator.py` — evaluator + EvalError
- `calc/test_evaluator.py` — unittest suite covering D1D3
- `calc.py` — CLI entry point
- Commit: (see git log — latest commit on main)

View File

@ -0,0 +1,98 @@
# STATUS-lex.md
## DONE
All DoD gates Adversary-verified PASS. Phase `lex` complete.
- D1: PASS @2026-06-15T04:34:35Z
- D2: PASS @2026-06-15T04:34:35Z
- D3: PASS @2026-06-15T04:40:18Z (AF-1 fixed: bare `.` now raises LexError)
- D4: PASS @2026-06-15T04:40:18Z (21 tests, 0 failures)
Fix commit: f40a364
---
## Gate D1 — Numbers CLAIMED
**WHAT:** `tokenize()` converts integers and floats to `NUMBER` tokens with numeric values.
**HOW to verify:**
```bash
python -c "from calc.lexer import tokenize; r=tokenize('42'); print(r[0].kind, r[0].value, type(r[0].value).__name__)"
python -c "from calc.lexer import tokenize; r=tokenize('3.14'); print(r[0].kind, r[0].value, type(r[0].value).__name__)"
python -c "from calc.lexer import tokenize; r=tokenize('.5'); print(r[0].kind, r[0].value)"
python -c "from calc.lexer import tokenize; r=tokenize('10.'); print(r[0].kind, r[0].value, type(r[0].value).__name__)"
python -c "from calc.lexer import tokenize; print([(t.kind,t.value) for t in tokenize('42')])"
```
**EXPECTED:**
- `NUMBER 42 int`
- `NUMBER 3.14 float`
- `NUMBER 0.5`
- `NUMBER 10.0 float`
- `[('NUMBER', 42), ('EOF', None)]`
**WHERE:** `calc/lexer.py`, commit fb03159
---
## Gate D2 — Operators & Parens CLAIMED
**WHAT:** `+ - * / ( )` tokenize to correct kinds; `"1+2*3"` → NUMBER PLUS NUMBER STAR NUMBER EOF.
**HOW to verify:**
```bash
python -c "from calc.lexer import tokenize; print([t.kind for t in tokenize('1+2*3')])"
python -c "from calc.lexer import tokenize; print([(t.kind,t.value) for t in tokenize('+-*/()')] )"
```
**EXPECTED:**
- `['NUMBER', 'PLUS', 'NUMBER', 'STAR', 'NUMBER', 'EOF']`
- `[('PLUS', '+'), ('MINUS', '-'), ('STAR', '*'), ('SLASH', '/'), ('LPAREN', '('), ('RPAREN', ')'), ('EOF', None)]`
**WHERE:** `calc/lexer.py`, commit fb03159
---
## Gate D3 — Whitespace & Errors RE-CLAIMED (AF-1 fixed)
**WHAT:** Spaces/tabs skipped; ALL invalid inputs raise `LexError` (including bare `.`).
**Fix applied:** Wrapped `float(raw)` / `int(raw)` conversion in try/except; raises `LexError` on bad numeric literals. Added `test_bare_dot_raises_lex_error` to test suite.
**HOW to verify:**
```bash
python -m unittest -q
python -c "from calc.lexer import tokenize; print([t.kind for t in tokenize(' 12 + 3 ')])"
python -c "from calc.lexer import tokenize; tokenize('1 @ 2')"
python -c "from calc.lexer import tokenize; tokenize('.')"
```
**EXPECTED:**
- `Ran 21 tests in 0.000s\nOK`
- `['NUMBER', 'PLUS', 'NUMBER', 'EOF']`
- Raises `calc.lexer.LexError: unexpected character '@' at position 2`
- Raises `calc.lexer.LexError: invalid number literal '.' at position 0`
**WHERE:** `calc/lexer.py`, `calc/test_lexer.py` (see fix commit)
---
## Gate D4 — Tests Green CLAIMED
**WHAT:** `calc/test_lexer.py` passes under `python -m unittest` with 0 failures.
**HOW to verify:**
```bash
python -m unittest -q
python -c "from calc.lexer import tokenize; print([(t.kind,t.value) for t in tokenize('3.5*(1-2)')])"
python -c "from calc.lexer import tokenize; tokenize('1 @ 2')"
```
**EXPECTED:**
- `Ran 20 tests in 0.000s\nOK`
- `[('NUMBER', 3.5), ('STAR', '*'), ('LPAREN', '('), ('NUMBER', 1), ('MINUS', '-'), ('NUMBER', 2), ('RPAREN', ')'), ('EOF', None)]`
- Raises `LexError`
**WHERE:** `calc/test_lexer.py`, commit fb03159

View File

@ -0,0 +1,126 @@
# STATUS-parse.md
## DONE
All DoD gates Adversary-verified PASS. Phase `parse` complete.
- D1: PASS @2026-06-15T04:41:47Z
- D2: PASS @2026-06-15T04:41:47Z
- D3: PASS @2026-06-15T04:41:47Z
- D4: PASS @2026-06-15T04:41:47Z
- D5: PASS @2026-06-15T04:41:47Z
- D6: PASS @2026-06-15T04:41:47Z
---
## Gate D1D6 CLAIMED (archived)
---
## AST Shape
Nodes defined in `calc/parser.py`:
```python
Num(value) # numeric leaf; value is int or float
BinOp(op, left, right) # binary: op in {'+','-','*','/'}; left/right are nodes
Unary(op, operand) # unary: op == '-'; operand is a node
```
All nodes implement `__repr__` and `__eq__`.
---
## D1 — Precedence
**WHAT:** `*` and `/` bind tighter than `+` and `-`.
**HOW:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('1+2*3'))))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('2*3+4'))))"
```
**EXPECTED:**
- `BinOp('+', Num(1), BinOp('*', Num(2), Num(3)))`
- `BinOp('+', BinOp('*', Num(2), Num(3)), Num(4))`
---
## D2 — Left Associativity
**WHAT:** Same-precedence operators associate left.
**HOW:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('8-3-2'))))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('8/4/2'))))"
```
**EXPECTED:**
- `BinOp('-', BinOp('-', Num(8), Num(3)), Num(2))`
- `BinOp('/', BinOp('/', Num(8), Num(4)), Num(2))`
---
## D3 — Parentheses
**WHAT:** Parens override precedence.
**HOW:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('(1+2)*3'))))"
```
**EXPECTED:**
- `BinOp('*', BinOp('+', Num(1), Num(2)), Num(3))`
---
## D4 — Unary Minus
**WHAT:** Leading and nested unary minus parses correctly.
**HOW:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('-5'))))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('-(1+2)'))))"
python -c "from calc.lexer import tokenize; from calc.parser import parse; print(repr(parse(tokenize('3 * -2'))))"
```
**EXPECTED:**
- `Unary('-', Num(5))`
- `Unary('-', BinOp('+', Num(1), Num(2)))`
- `BinOp('*', Num(3), Unary('-', Num(2)))`
---
## D5 — Errors
**WHAT:** Malformed input raises `ParseError`.
**HOW:**
```bash
python -c "from calc.lexer import tokenize; from calc.parser import parse, ParseError
for s in ['1 +','(1','1 2',')(','']:
try: parse(tokenize(s)); print('NO ERROR for', repr(s))
except ParseError as e: print('OK ParseError:', repr(s), '->', e)
"
```
**EXPECTED:** All five raise `ParseError` (not any other exception type).
---
## D6 — Tests Green
**WHAT:** `python -m unittest -q` passes with 0 failures; covers D1D5.
**HOW:**
```bash
python -m unittest -q
```
**EXPECTED:** `Ran 48 tests in ...s\n\nOK` (21 lex + 27 parser)
**WHERE:** `calc/parser.py`, `calc/test_parser.py`