# TCK Improvement Phase Plans

**Date**: 2026-02-09
**Created After**: Temporal implementation, Quantifier fix
**Last Updated**: 2026-02-09 (after function case preservation and CREATE fixes)

---

## Implementation Progress

### Completed Fixes ✅

| Fix | Tests Fixed | Details |
|-----|-------------|---------|
| Boolean AND/OR/XOR/NOT validation | +113 | Added `InvalidArgumentType` validation in strict mode |
| Integer overflow validation | +3 | Added `IntegerOverflow` for integers exceeding 64-bit range |
| Data path split fix | +6+ | Fixed `_data_path_to_entity_name_attribute` for expressions with decimals |
| NaN division handling | +4 | Float `0.0/0.0` now produces NaN, `x/0.0` produces Infinity |
| NaN comparison semantics | +4 | NaN = x → false, NaN <> x → true, NaN </<= x → false (or null for non-numbers) |
| Map/List null comparison | +6 | `{k:null} = {k:null}` → null, `[null] = [1]` → null |
| Path detection fix | +2 | Single-element lists no longer treated as paths in comparison |
| IN operator validation | +5 | `1 IN true` raises InvalidArgumentType in strict mode |
| List slice with null bounds | +6 | `list[null..null]` → null, but `list[..2]` still works |
| Per-row UNWIND evaluation | +2 | Multiple UNWINDs now properly cross-join per-row |
| NULL literal handling | +2 | Fixed `RETURN null` by handling NULL_W token (Token is subclass of str) |
| Complex aggregation args | +3 | `collect([0,0.0])` now works - expression tree stored for evaluation |
| Function case preservation | +3 | `labels(m)` returns `labels(m)` not `LABELS(m)` |
| CREATE anonymous nodes | +5 | Fixed comma-separated CREATE patterns with anonymous nodes |
| MultiDiGraph edge access | +2 | Fixed edge data access using `get_edge_data()` |
| SIZE/LENGTH null handling | +1 | `size(null)` and `length(null)` return null |
| List indexing validation | +4 | `list["1"]` and `list[true]` raise InvalidArgumentType |

### Current Results (After All Fixes)

| Category | Before | After | Delta | Notes |
|----------|--------|-------|-------|-------|
| Boolean | 17/150 (11%) | 150/150 (100%) | +133 | Full compliance! |
| Comparison | 39/72 (54%) | 68/72 (94%) | +29 | Function case, path, edge fixes |
| List | 100/185 (54%) | 127/185 (69%) | +27 | IN validation, slice, null, indexing fixes |
| Literals | 100/131 (76%) | 105/131 (80%) | +5 | IntegerOverflow, NULL literal |
| Quantifier 1-3 | 293/316 (93%) | 293/316 (93%) | +0 | Previously working |

**Total Scenarios: 1928 passed / 3897 total (49.5%)**

## Summary (Remaining Issues)

| Category | Current | Pass Rate | Remaining Failures | Root Causes |
|----------|---------|-----------|-------------------|-------------|
| Comparison | 68/72 | 94% | 4 | Relationship comparison, path equality, undefined vars, cross-type UNWIND |
| Boolean | 150/150 | 100% | 0 | ✅ Complete! |
| List | 127/185 | 69% | 58 | Pattern comprehension, size() on paths, size(null) in WITH context |
| Literals | 105/131 | 80% | 26 | String escapes, deep nesting, map key validation |

---

## Phase 1: Boolean Expressions (133 failures → ~20 failures)

**Priority**: HIGH (11% → ~85%)
**Impact**: +113 tests
**Root Causes**: 2 distinct issues

### Issue 1A: Variable Resolution in Boolean Context (4 failures)
**Pattern**: `Unknown entity name: a`

**Symptoms**:
```
ASSERT FAILED: Expected result but got error: Unknown entity name: a
```

**Failing Queries**:
```cypher
MATCH (a) RETURN a.prop AND true
MATCH (a) RETURN a.prop OR false
```

**Root Cause**: Expression evaluation doesn't resolve variables in AND/OR contexts.

**Fix Location**: `nxcypher/__init__.py` - `_evaluate_and_expression()` / `_evaluate_or_expression()`

**Implementation**:
```python
def _evaluate_and_expression(self, tree, context):
    for child in tree.children:
        if isinstance(child, Tree):
            # Ensure variable lookup happens before evaluation
            val = self._evaluate(child, context)
            # ...existing logic
```

### Issue 1B: InvalidArgumentType Validation (129 failures)
**Pattern**: `Expected SyntaxError (InvalidArgumentType) but query succeeded`

**Symptoms**:
```
Expected SyntaxError (InvalidArgumentType) but query succeeded with: {'123ANDtrue': [True]}
Expected SyntaxError (InvalidArgumentType) but query succeeded with: {'[]ANDfalse': [False]}
Expected SyntaxError (InvalidArgumentType) but query succeeded with: {'{}ANDtrue': [False]}
```

**Failing Queries**:
```cypher
RETURN 123 AND true       -- number AND boolean (invalid)
RETURN 'foo' AND true     -- string AND boolean (invalid)
RETURN [] AND false       -- list AND boolean (invalid)
RETURN {} AND true        -- map AND boolean (invalid)
RETURN NOT 123            -- NOT on non-boolean (invalid)
```

**Root Cause**: AND/OR/NOT operators accept any type instead of requiring boolean operands.

**Fix Location**: `nxcypher/interpreter.py` - strict mode boolean validation

**Implementation**:
```python
def _validate_boolean_operand(self, value, operator):
    """Validate operand is boolean in strict mode."""
    if self.strict and value is not None and not isinstance(value, bool):
        raise InvalidArgumentType(
            f"Type mismatch: {operator} requires boolean operands, "
            f"got {type(value).__name__}"
        )

def _evaluate_and_expression(self, tree, context):
    left = self._evaluate(tree.children[0], context)
    self._validate_boolean_operand(left, "AND")
    # Skip token
    right = self._evaluate(tree.children[2], context)
    self._validate_boolean_operand(right, "AND")
    # Three-valued logic
    if left is False or right is False:
        return False
    if left is None or right is None:
        return None
    return True
```

---

## Phase 2: Comparison Expressions (33 failures → ~5 failures)

**Priority**: HIGH (54% → ~93%)
**Impact**: +28 tests
**Root Causes**: 3 distinct issues

### Issue 2A: Unevaluated Tree Objects (3 failures)
**Pattern**: `Unknown entity name: Tree(Token('RULE', 'list_lit'), ...)`

**Symptoms**:
```
Unknown entity name: Tree(Token('RULE', 'list_lit'), [Token('LBRACK', '['), ...])
```

**Failing Queries**:
```cypher
RETURN [0, 0.0] = [0.0, 0]  -- comparing list literals
RETURN [0.5, 0] = [0, 0.5]
RETURN ['0', 0] = [0, '0']
```

**Root Cause**: Expression evaluation not recursing into list literals when used in comparisons.

**Fix Location**: `nxcypher/__init__.py` - `_evaluate_comparison_expression()`

**Implementation**:
```python
def _evaluate_comparison_expression(self, tree, context):
    # Ensure all operands are fully evaluated
    for i, child in enumerate(tree.children):
        if isinstance(child, Tree):
            # Force evaluation of Tree nodes
            evaluated = self._evaluate(child, context)
            # Replace tree with evaluated value for comparison
```

### Issue 2B: Tuple Unpacking in Path Comparison (11 failures)
**Pattern**: `too many values to unpack (expected 2, got 3)`

**Symptoms**:
```
Expected result but got error: too many values to unpack (expected 2, got 3)
Expected result but got error: too many values to unpack (expected 2, got 4)
Expected result but got error: too many values to unpack (expected 2, got 5)
```

**Failing Queries**:
```cypher
MATCH p = (a)-[r]->(b)
RETURN p = p, p <> p
```

**Root Cause**: Path comparison code expects 2-tuple but paths contain more elements.

**Fix Location**: `nxcypher/__init__.py` - path comparison logic

**Implementation**: Find path comparison and fix tuple handling:
```python
# BEFORE (bug):
a, b = path  # Fails when path has more elements

# AFTER (fix):
if isinstance(left, tuple) and isinstance(right, tuple):
    # Compare paths element by element
    return left == right
```

### Issue 2C: Map Comparison Logic (8 failures)
**Pattern**: `Expected row not found in actual results`

**Failing Queries**:
```cypher
RETURN {a: 1} = {a: 1}
RETURN {a: 1, b: 2} = {b: 2, a: 1}
```

**Root Cause**: Map comparison may not be working correctly.

### Issue 2D: UndefinedVariable Validation (1 failure)
**Pattern**: `Expected SyntaxError (UndefinedVariable)`

**Failing Query**:
```cypher
RETURN a = 1  -- 'a' not defined
```

**Root Cause**: Missing validation for undefined variables in strict mode.

---

## Phase 3: List Expressions (85 failures → ~15 failures)

**Priority**: MEDIUM (54% → ~92%)
**Impact**: +70 tests
**Root Causes**: 4 distinct issues

### Issue 3A: List Indexing Type Validation (30 failures)
**Pattern**: `Expected TypeError (InvalidArgumentType) but query succeeded`

**Symptoms**:
```
Expected TypeError (InvalidArgumentType) but query succeeded with: {'list[idx]': [None]}
Expected TypeError (InvalidArgumentType) but query succeeded with: {'list[idx]': ['1']}
```

**Failing Queries**:
```cypher
RETURN [1, 2, 3]['a']     -- string index (invalid)
RETURN [1, 2, 3][true]    -- boolean index (invalid)
RETURN [1, 2, 3][{a: 1}]  -- map index (invalid)
```

**Root Cause**: List indexing accepts any type instead of requiring integer.

**Fix Location**: `nxcypher/__init__.py` - list indexing evaluation

**Implementation**:
```python
def _evaluate_list_index(self, list_val, index_val, context):
    if index_val is not None and not isinstance(index_val, int):
        if self.strict:
            raise TypeError(
                f"Type mismatch: list index must be integer, "
                f"got {type(index_val).__name__}"
            )
        return None  # Lenient mode returns null
    # ...existing indexing logic
```

### Issue 3B: IN Operator on Non-List (5 failures)
**Pattern**: `Expected SyntaxError but query succeeded`

**Failing Queries**:
```cypher
RETURN 1 IN 'abc'        -- IN on string (invalid)
RETURN 1 IN 123          -- IN on integer (invalid)
RETURN 1 IN true         -- IN on boolean (invalid)
```

**Root Cause**: IN operator accepts non-list right operand.

### Issue 3C: size() Function Validation (15 failures)
**Pattern**: `Expected TypeError but query succeeded`

**Failing Queries**:
```cypher
MATCH p = (a)-[*]->(b)
RETURN size(p)           -- size() on path (invalid)
```

**Root Cause**: size() function accepts paths instead of only lists/strings.

### Issue 3D: List Slice Edge Cases (20 failures)
**Pattern**: `Expected row not found in actual results`

**Failing Queries**:
```cypher
RETURN [1, 2, 3][-1..]    -- negative slice start
RETURN [1, 2, 3][..-1]    -- negative slice end
RETURN [1, 2, 3][0..5]    -- slice beyond bounds
```

**Root Cause**: Slice handling for edge cases.

### Issue 3E: Pattern Comprehension size() (15 failures)
**Pattern**: Various

**Failing Queries**:
```cypher
MATCH (n)
RETURN size([(n)-->(m) | m.prop])
```

---

## Phase 4: Literals (31 failures → ~5 failures)

**Priority**: LOW (76% → ~96%)
**Impact**: +26 tests
**Root Causes**: 4 distinct issues

### Issue 4A: Integer Overflow Validation (6 failures)
**Pattern**: `Expected SyntaxError (IntegerOverflow) but query succeeded`

**Symptoms**:
```
Expected SyntaxError (IntegerOverflow) but query succeeded with: {'literal': [9223372036854775808]}
Expected SyntaxError (IntegerOverflow) but query succeeded with: {'literal': [-9223372036854775809]}
```

**Failing Queries**:
```cypher
RETURN 9223372036854775808     -- exceeds Long.MAX_VALUE
RETURN -9223372036854775809    -- exceeds Long.MIN_VALUE
```

**Root Cause**: No validation of integer literal bounds.

**Fix Location**: Parser or literal evaluation

**Implementation**:
```python
MAX_INT = 9223372036854775807   # 2^63 - 1
MIN_INT = -9223372036854775808  # -2^63

def _evaluate_integer_literal(self, token):
    value = int(token)
    if value > MAX_INT or value < MIN_INT:
        raise IntegerOverflow(f"Integer literal {value} out of range")
    return value
```

### Issue 4B: Null Literal Handling (2 failures)
**Pattern**: `Unknown entity name: null`

**Failing Queries**:
```cypher
RETURN null
RETURN NULL
```

**Root Cause**: `null` keyword not recognized in certain contexts.

**Fix Location**: `_evaluate()` or atom handling

### Issue 4C: String Escape Sequences (8 failures)
**Pattern**: `Expected row not found`

**Failing Queries**:
```cypher
RETURN 'foo\'bar'      -- escaped single quote
RETURN 'foo\\bar'      -- escaped backslash
RETURN '\u0041'        -- Unicode escape
```

**Root Cause**: String literal parsing doesn't handle all escapes.

### Issue 4D: Deep Nesting (4 failures)
**Pattern**: `Expected row not found`

**Failing Queries**:
```cypher
RETURN [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
```

**Root Cause**: 40-level nesting may exceed recursion or have evaluation issues.

### Issue 4E: InvalidNumberLiteral (6 failures)
**Pattern**: `Expected SyntaxError (InvalidNumberLiteral)`

**Failing Queries**:
```cypher
RETURN 0x      -- incomplete hex
RETURN 0o      -- incomplete octal
RETURN 1e      -- incomplete exponent
```

---

## Implementation Order

### Recommended Sequence

| Order | Phase | Tests Fixed | New Pass Rate | Effort |
|-------|-------|-------------|---------------|--------|
| 1 | Boolean (1B) | +113 | ~45% total | 2-3 hours |
| 2 | Comparison (2A, 2B) | +14 | ~48% total | 2 hours |
| 3 | List (3A, 3B) | +35 | ~52% total | 2 hours |
| 4 | Literals (4A, 4B) | +8 | ~53% total | 1 hour |
| 5 | Remaining issues | +20 | ~55% total | 3-4 hours |

### Quick Wins First

1. **Boolean InvalidArgumentType** (129 tests) - Single validation function
2. **Integer Overflow** (6 tests) - Simple bounds check
3. **Null literal** (2 tests) - Token recognition
4. **List indexing type** (30 tests) - Type check before index

### Total Expected Improvement

- **Before**: ~1178 passed (30.2%)
- **After Phase 4 complete**: ~1400+ passed (~36%)
- **Combined with temporal + quantifier fixes**: ~1600+ passed (~41%)

---

## File Modification Summary

| File | Changes |
|------|---------|
| `nxcypher/__init__.py` | Boolean validation, list indexing, integer overflow, null handling |
| `nxcypher/interpreter.py` | InvalidArgumentType exception class, strict mode extensions |
| `features/steps/cypher_steps.py` | Error type matching improvements (if needed) |

---

## Verification Commands

```bash
# Test Boolean after fix
poetry run behave features/expressions/boolean/

# Test Comparison after fix
poetry run behave features/expressions/comparison/

# Test List after fix
poetry run behave features/expressions/list/

# Test Literals after fix
poetry run behave features/expressions/literals/

# Full TCK suite
poetry run behave
```
