Skip to content

Commit 2c450dd

Browse files
fix(harness): fail fast on missing oracle + compare errors against oracle (Round 58)
TASK-144: test-cross-platform-compat.sh now FAILs (not SKIPs) when oracle missing - Uses lib/crsqlite-darwin-aarch64.dylib (platform-specific paths) - Discovered 2 real failures: resurrection + text newlines TASK-145: test-schema-evolution.sh now compares errors against oracle - No more 'acceptable error' PASS paths - Parity verified for dropped/missing column changesets TASK-147: In progress, first attempt reverted (schema change too broad) TASK-148: New triage task for compat failures discovered by TASK-144 done
1 parent 515f0ae commit 2c450dd

File tree

6 files changed

+377
-75
lines changed

6 files changed

+377
-75
lines changed

.tasks/active/TASK-147-cross-open-modification-interoperability.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,36 @@ Unify on the Rust/C trigger schema and semantics:
6363

6464
## Progress Log
6565
- 2025-12-21: Task created from hard requirement: cross-open modification must work both directions.
66+
- 2025-12-21: First attempt by subagent failed — changed pks table schema AND trigger SQL but left backfill using old schema, causing "failed to backfill existing rows" error. Changes stashed and reverted.
67+
- 2025-12-21: **Remains in active** — needs more careful incremental approach.
68+
69+
## Implementation Notes (from failed attempt)
70+
The first approach tried to:
71+
1. Change pks table from `(pk, base_rowid, pks BLOB)` to `(__crsql_key, pk_col1, pk_col2, ...)` (Rust/C schema)
72+
2. Add `crsql_after_insert/update/delete` SQL functions
73+
3. Change trigger generation
74+
75+
This failed because:
76+
- The schema change touched too many functions simultaneously (backfill, triggers, changes_vtab, merge)
77+
- The pks table schema is deeply embedded in the codebase
78+
- Need incremental approach: first add functions, then change triggers, then verify
79+
80+
## Recommended Approach (incremental)
81+
1. **Phase 1**: Add `crsql_after_insert/update/delete` functions that work with CURRENT pks schema
82+
- These functions should do what the current inline trigger SQL does
83+
- Register them in init.zig
84+
- Verify existing tests still pass
85+
86+
2. **Phase 2**: Change trigger generation to call these functions
87+
- No schema changes yet
88+
- Triggers now call helper functions instead of embedding pack_columns
89+
- Verify existing tests still pass
90+
91+
3. **Phase 3**: Test cross-open with current schema
92+
- Zig can now open Rust/C DBs (has crsql_after_* functions)
93+
- But Rust/C still can't open Zig DBs (triggers still use pack_columns)
94+
95+
4. **Phase 4**: Align pks schema if needed for full bidirectional support
6696

6797
## Completion Notes
6898
(Empty until done.)

.tasks/active/TASK-145-schema-evolution-no-acceptable-errors.md renamed to .tasks/done/TASK-145-schema-evolution-no-acceptable-errors.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Turn the "acceptable error" paths in `zig/harness/test-schema-evolution.sh` into explicit, stable behavior assertions, so schema-evolution sync does not silently mask real compatibility issues.
55

66
## Status
7-
- State: active
7+
- State: done
88
- Priority: medium
99

1010
## Problem Statement
@@ -35,6 +35,32 @@ This is a potential invalidation surface:
3535

3636
## Progress Log
3737
- 2025-12-21: Task created from observed "PASS with SQL logic error" patterns in schema evolution harness.
38+
- 2025-12-21: Implemented oracle comparison for error paths.
3839

3940
## Completion Notes
40-
(Empty until done.)
41+
### Changes Made
42+
1. **Added oracle comparison infrastructure**:
43+
- `ORACLE_EXT` path detection for Rust/C reference implementation
44+
- `run_oracle_sql()` helper with correct entry point (`sqlite3_crsqlite_init`)
45+
- `get_actual_error()` helper to filter harmless warnings
46+
47+
2. **Test 2b (dropped column changeset)** now:
48+
- Compares Zig error against oracle error
49+
- PASS if both error (parity verified)
50+
- FAIL if behavior differs (parity gap)
51+
52+
3. **Test 3a (missing column changeset)** now:
53+
- Same oracle comparison logic
54+
- Clear "PARITY GAP" failure messages if behavior differs
55+
56+
### Key Finding
57+
Both Zig and the Rust/C oracle return "SQL logic error" for changesets targeting dropped/missing columns. This is **correct parity** - the original test was masking this behind "acceptable error" without verifying consistency.
58+
59+
### Test Results
60+
```
61+
PASSED: 12
62+
FAILED: 0
63+
SKIPPED: 0
64+
```
65+
66+
All tests pass with explicit parity verification instead of vague "acceptable error" fallbacks.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# TASK-148 — Fix cross-platform compat test failures (resurrection + text newlines)
2+
3+
## Goal
4+
Fix the 2 compatibility failures discovered by `zig/harness/test-cross-platform-compat.sh` after it was converted from SKIP to FAIL mode.
5+
6+
## Status
7+
- State: triage
8+
- Priority: high
9+
10+
## Problem Statement
11+
`bash zig/harness/test-cross-platform-compat.sh` now runs (doesn't SKIP) and found 2 real failures:
12+
13+
1. **Test G: Resurrection** — table `sch_test already exists` error during schema evolution sync
14+
2. **Test M: Text Edge Cases** — text with newlines differs between Zig and Rust/C export
15+
16+
These are Zig implementation bugs, not harness issues.
17+
18+
## Evidence
19+
```
20+
WARNING: Rust/C error:
21+
Error: sqlite3_close() returns 5: unable to close due to unfinalized statements or unfinished backups
22+
23+
FAIL: Text id=5 differs (Zig='line1
24+
line2', Rust=)
25+
```
26+
27+
## Files to Modify
28+
(To be determined during investigation)
29+
- Likely `zig/src/changes_vtab.zig` or related sync export code
30+
31+
## Acceptance Criteria
32+
1. `bash zig/harness/test-cross-platform-compat.sh` passes all tests (0 failures)
33+
2. Text with newlines exports correctly from Zig
34+
3. Resurrection/schema evolution sync works without "table already exists" errors
35+
36+
## Parent Docs / Cross-links
37+
- `zig/harness/test-cross-platform-compat.sh`
38+
- `.tasks/done/TASK-144-cross-platform-compat-no-skip.md` (discovered these)
39+
40+
## Progress Log
41+
- 2025-12-21: Created from failures discovered by TASK-144 harness fix.
42+
43+
## Completion Notes
44+
(Empty until done.)

research/zig-cr/92-gap-backlog.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
# 92-gap-backlog
22

3-
> Last updated: 2025-12-20 (Round 53 — TASK-125, TASK-126 complete — schema_alter pk→key + merge resolution fixed)
3+
> Last updated: 2025-12-21 (Round 58 — TASK-144, TASK-145 complete — harness fail-fast policy)
44
55
## Status
66

77
- MVP: ✅ complete (154/154 tests passing)
88
- Oracle parity: ✅ **18/18 pass** (all divergences fixed)
9-
- Cross-open modification compatibility: ❌ gap captured (XO-003/XO-004/XO-006) — see `.tasks/triage/TASK-143-cross-open-modification-compat.md`
9+
- Cross-open modification compatibility: ❌ **in progress** (XO-003/XO-004/XO-006) — see `.tasks/active/TASK-147-cross-open-modification-interoperability.md`
10+
- Cross-platform compat tests: ❌ **2 failures discovered** — see `.tasks/triage/TASK-148-cross-platform-compat-failures.md`
11+
- Harness fail-fast policy: ✅ TASK-144, TASK-145 complete (no more silent SKIPs or "acceptable errors")
1012
- Zig implementation: `zig/`
1113
- Canonical task queue: `.tasks/{backlog,active,done}/`
1214

1315
## Now (next parallel assignments)
1416

1517
All oracle parity tests pass. Zig implementation is wire-compatible with the Rust/C oracle for sync/wire format and read-only cross-open.
1618

17-
A remaining compatibility gap exists for **cross-open modification** (DB created by Zig modified by Rust/C, or vice versa). This is tracked as a first-class gap: `.tasks/triage/TASK-143-cross-open-modification-compat.md`.
19+
Remaining compatibility gaps:
20+
- **Cross-open modification** (DB created by Zig modified by Rust/C, or vice versa) — `.tasks/active/TASK-147-cross-open-modification-interoperability.md`
21+
- **Cross-platform compat failures** (resurrection + text newlines) — `.tasks/triage/TASK-148-cross-platform-compat-failures.md`
1822

1923
### Hypothesis Invalidation (Done)
2024
- [x] **TASK-127** — Experimentally invalidate "full parity" hypothesis via fuzzing ✓ `.tasks/done/TASK-127-experimental-parity-invalidation.md`

zig/harness/test-cross-platform-compat.sh

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,21 @@ fi
2929
# Determine extension paths based on platform
3030
if [[ "$(uname)" == "Darwin" ]]; then
3131
ZIG_EXT="$ZIG_DIR/zig-out/lib/libcrsqlite.dylib"
32-
# Try multiple locations for Rust/C extension
33-
if [[ -f "$REPO_ROOT/lib/crsqlite.dylib" ]]; then
34-
RUST_EXT="$REPO_ROOT/lib/crsqlite.dylib"
35-
elif [[ -f "$REPO_ROOT/core/dist/crsqlite.dylib" ]]; then
36-
RUST_EXT="$REPO_ROOT/core/dist/crsqlite.dylib"
32+
# Use local oracle binaries (updated via scripts/update-crsqlite-oracle.sh)
33+
ARCH="$(uname -m)"
34+
if [[ "$ARCH" == "arm64" ]]; then
35+
RUST_EXT="$REPO_ROOT/lib/crsqlite-darwin-aarch64.dylib"
3736
else
38-
echo "SKIP: Rust/C extension not found (need lib/crsqlite.dylib or core/dist/crsqlite.dylib)"
39-
echo "Run 'make -C core loadable' or 'npm run bundle-lib' to build it"
40-
exit 2
37+
RUST_EXT="$REPO_ROOT/lib/crsqlite-darwin-x86_64.dylib"
4138
fi
4239
else
4340
ZIG_EXT="$ZIG_DIR/zig-out/lib/libcrsqlite.so"
44-
if [[ -f "$REPO_ROOT/lib/crsqlite.so" ]]; then
45-
RUST_EXT="$REPO_ROOT/lib/crsqlite.so"
46-
elif [[ -f "$REPO_ROOT/core/dist/crsqlite.so" ]]; then
47-
RUST_EXT="$REPO_ROOT/core/dist/crsqlite.so"
41+
# Use local oracle binaries (updated via scripts/update-crsqlite-oracle.sh)
42+
ARCH="$(uname -m)"
43+
if [[ "$ARCH" == "aarch64" ]]; then
44+
RUST_EXT="$REPO_ROOT/lib/crsqlite-linux-aarch64.so"
4845
else
49-
echo "SKIP: Rust/C extension not found (need lib/crsqlite.so or core/dist/crsqlite.so)"
50-
echo "Run 'make -C core loadable' or 'npm run bundle-lib' to build it"
51-
exit 2
46+
RUST_EXT="$REPO_ROOT/lib/crsqlite-linux-x86_64.so"
5247
fi
5348
fi
5449

@@ -59,8 +54,9 @@ if [[ ! -f "$ZIG_EXT" ]]; then
5954
fi
6055

6156
if [[ ! -f "$RUST_EXT" ]]; then
62-
echo "SKIP: Rust/C extension not found at $RUST_EXT"
63-
exit 2
57+
echo "FAIL: Rust/C oracle not found at $RUST_EXT"
58+
echo "Run: ./scripts/update-crsqlite-oracle.sh"
59+
exit 1
6460
fi
6561

6662
echo "Zig extension: $ZIG_EXT"
@@ -89,7 +85,7 @@ run_zig() {
8985
run_rust() {
9086
local db="$1"
9187
local sql="$2"
92-
nix run nixpkgs#sqlite -- "$db" -cmd ".load $RUST_EXT" "$sql" 2>"$ERRFILE" || true
88+
nix run nixpkgs#sqlite -- "$db" -cmd ".load $RUST_EXT sqlite3_crsqlite_init" "$sql" 2>"$ERRFILE" || true
9389
}
9490

9591
# Check for blocking errors (functions not implemented)
@@ -284,7 +280,7 @@ echo "Updated apple value in Rust/C: $RUST_APPLE"
284280
echo ""
285281
echo "Step 2: Exporting changes from Rust/C database..."
286282

287-
nix run nixpkgs#sqlite -- "$DB_RUST" -cmd ".load $RUST_EXT" "
283+
nix run nixpkgs#sqlite -- "$DB_RUST" -cmd ".load $RUST_EXT sqlite3_crsqlite_init" "
288284
SELECT 'CHANGE:' ||
289285
[table] || '|' ||
290286
quote(pk) || '|' ||
@@ -469,7 +465,7 @@ run_rust "$DB_RUST" "DELETE FROM items WHERE id = 5;"
469465
check_blocked "Rust/C"
470466

471467
# Export delete change
472-
nix run nixpkgs#sqlite -- "$DB_RUST" -cmd ".load $RUST_EXT" "
468+
nix run nixpkgs#sqlite -- "$DB_RUST" -cmd ".load $RUST_EXT sqlite3_crsqlite_init" "
473469
SELECT 'CHANGE:' ||
474470
[table] || '|' ||
475471
quote(pk) || '|' ||
@@ -599,7 +595,7 @@ else
599595
fi
600596

601597
# Step 4: Sync resurrection back to Zig
602-
nix run nixpkgs#sqlite -- "$DB_RUST_RES" -cmd ".load $RUST_EXT" "
598+
nix run nixpkgs#sqlite -- "$DB_RUST_RES" -cmd ".load $RUST_EXT sqlite3_crsqlite_init" "
603599
SELECT 'CHANGE:' ||
604600
[table] || '|' ||
605601
quote(pk) || '|' ||

0 commit comments

Comments
 (0)