Skip to content

Commit 8586645

Browse files
fix(zig): clock schema parity + site_id cross-open (TASK-123, TASK-124)
1 parent eed120c commit 8586645

12 files changed

+356
-152
lines changed

.tasks/DELEGATE_WORK_HANDOFF.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,84 @@ Artifacts:
6868

6969
---
7070

71+
## Round 2025-12-20 (52) — Fix clock schema + site_id cross-open parity (2 tasks)
72+
73+
**Tasks executed**
74+
- `.tasks/done/TASK-123-fix-clock-table-schema-parity.md`
75+
- `.tasks/done/TASK-124-fix-site-id-cross-open-parity.md`
76+
77+
**Commits**
78+
- (pending commit)
79+
80+
**Environment**
81+
- OS: darwin (macOS ARM64)
82+
- Tooling: nix, zig (via nix), bash
83+
84+
**Commands run (exact)**
85+
```bash
86+
bash zig/harness/test-oracle-parity.sh
87+
```
88+
89+
**Outputs (paste)**
90+
91+
<details>
92+
<summary>TASK-123: Clock table schema parity (PASS)</summary>
93+
94+
```text
95+
Test 2: Clock Table Schema Parity
96+
Test 2a: __crsql_clock table columns
97+
PASS: __crsql_clock schema matches
98+
Test 2b: __crsql_clock index structure
99+
PASS: __crsql_clock index count matches (1)
100+
```
101+
102+
**Fix:** Renamed `pk` column to `key` in clock table, added STRICT mode, added `_dbv_idx` index on `db_version`.
103+
104+
Files modified:
105+
- `zig/src/as_crr.zig` — clock table creation, triggers, backfill
106+
- `zig/src/merge_insert.zig` — statement caches and helper functions
107+
- `zig/src/schema_alter.zig` — alter table triggers and cleanup
108+
- `zig/src/changes_vtab.zig` — changes virtual table queries
109+
</details>
110+
111+
<details>
112+
<summary>TASK-124: Site ID cross-open parity (PASS)</summary>
113+
114+
```text
115+
Test 4b: Cross-open Zig DB with Rust/C preserves site_id
116+
PASS: Rust/C reads Zig's site_id correctly: C43B2B534A75413C9A212C62203D6F7F
117+
Test 4c: Cross-open Rust/C DB with Zig preserves site_id
118+
PASS: Zig reads Rust/C's site_id correctly: F58E991645D24B868C61EF88871EF980
119+
```
120+
121+
**Fix:** Added `crsqlite_version|160300` to `crsql_master` during init. Rust/C checks for this version entry before accepting an existing site_id.
122+
123+
Files modified:
124+
- `zig/src/ffi/init.zig` — added version writing logic
125+
</details>
126+
127+
<details>
128+
<summary>Oracle parity test summary</summary>
129+
130+
```text
131+
Oracle Parity Test Summary
132+
Results: 16 passed, 2 failed, 0 skipped
133+
```
134+
135+
Remaining failures (Test 3a/3b) are **merge resolution** divergences — unrelated to TASK-123/124.
136+
</details>
137+
138+
**Reproduction steps (clean checkout)**
139+
1. `git clone <repo> && cd cr-sqlite`
140+
2. `bash zig/harness/test-oracle-parity.sh` — verify Test 2a, 2b, 4b, 4c pass
141+
142+
**Known gaps / unverified claims**
143+
- 2 remaining oracle parity failures (merge resolution Test 3a/3b) are pre-existing
144+
- No coverage captured
145+
- CI integration not verified this round (local runs only)
146+
147+
---
148+
71149
## Round 2025-12-20 (51) — Fix remaining oracle divergences (2 tasks)
72150

73151
**Tasks executed**

.tasks/backlog/TASK-123-fix-clock-table-schema-parity.md

Lines changed: 0 additions & 35 deletions
This file was deleted.

.tasks/backlog/TASK-124-fix-site-id-cross-open-parity.md

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# TASK-123: Fix clock table schema parity with oracle
2+
3+
## Status
4+
- [x] Completed
5+
6+
## Priority
7+
medium
8+
9+
## Assigned To
10+
(completed)
11+
12+
## Parent Docs / Cross-links
13+
- Divergence documented in: `.tasks/done/TASK-074-cross-impl-compat-expanded.md`
14+
- Test: `zig/harness/test-oracle-parity.sh` (Test 2)
15+
- Zig clock table creation: `zig/src/as_crr.zig`
16+
- Gap backlog: `research/zig-cr/92-gap-backlog.md`
17+
18+
## Description
19+
The Zig `__crsql_clock` table schema differs from the Rust/C oracle in two ways:
20+
21+
1. **Column naming**: Zig uses `pk` column, Rust/C uses `key` column
22+
2. **Index**: Rust/C has an index on the clock table, Zig has 0 indexes
23+
3. **Strict**: Rust/C uses STRICT tables, Zig does not
24+
25+
These differences may cause cross-implementation database sharing issues.
26+
27+
## Files to Modify
28+
- `zig/src/as_crr.zig` - clock table creation
29+
30+
## Acceptance Criteria
31+
- [x] `__crsql_clock` table schema matches oracle exactly
32+
- [x] Column names match (change `pk` to `key` - careful with pks table relation!)
33+
- [x] Index structure matches oracle (add `_dbv_idx` on `db_version`)
34+
- [x] Strict mode enabled
35+
- [x] `zig/harness/test-oracle-parity.sh` Test 2 passes
36+
37+
## Progress Log
38+
- 2025-12-20: Fixed clock table schema parity
39+
40+
## Completion Notes
41+
### Changes Made
42+
Renamed the `pk` column to `key` in the `__crsql_clock` table to match the Rust/C oracle.
43+
Added `STRICT` mode to the table definition. Added `_dbv_idx` index on `db_version`.
44+
45+
Updated all SQL references to the clock table column in:
46+
- `zig/src/as_crr.zig` - clock table creation, triggers, backfill
47+
- `zig/src/merge_insert.zig` - merge statement caches and helper functions
48+
- `zig/src/schema_alter.zig` - alter table triggers and cleanup
49+
- `zig/src/changes_vtab.zig` - changes virtual table queries
50+
51+
Note: The `pk` column in the `__crsql_pks` table was NOT renamed (it's a different
52+
table with a different purpose - it maps packed PK blobs to auto-increment keys).
53+
54+
### Test Output
55+
```
56+
Test 2: Clock Table Schema Parity
57+
Test 2a: __crsql_clock table columns
58+
PASS: __crsql_clock schema matches
59+
Test 2b: __crsql_clock index structure
60+
PASS: __crsql_clock index count matches (1)
61+
```
62+
63+
### Zig Clock Table Schema (now matches oracle):
64+
```sql
65+
CREATE TABLE IF NOT EXISTS "test__crsql_clock" (
66+
"key" INTEGER NOT NULL,
67+
"col_name" TEXT NOT NULL,
68+
"col_version" INTEGER NOT NULL,
69+
"db_version" INTEGER NOT NULL,
70+
"site_id" INTEGER NOT NULL DEFAULT 0,
71+
"seq" INTEGER NOT NULL,
72+
PRIMARY KEY ("key", "col_name")
73+
) WITHOUT ROWID, STRICT;
74+
CREATE INDEX "test__crsql_clock_dbv_idx" ON "test__crsql_clock" ("db_version");
75+
```
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# TASK-124: Fix site_id preservation on cross-implementation DB open
2+
3+
## Status
4+
- [x] Completed
5+
6+
## Priority
7+
medium
8+
9+
## Assigned To
10+
(completed)
11+
12+
## Parent Docs / Cross-links
13+
- Divergence documented in: `.tasks/done/TASK-074-cross-impl-compat-expanded.md`
14+
- Test: `zig/harness/test-oracle-parity.sh` (Test 4b, 4c)
15+
- Zig site_id handling: `zig/src/site_identity.zig`
16+
- Zig init handling: `zig/src/ffi/init.zig`
17+
- Gap backlog: `research/zig-cr/92-gap-backlog.md`
18+
19+
## Description
20+
When Rust/C opens a database created by Zig, the site_id is not preserved correctly.
21+
22+
**Current behavior:**
23+
- Zig creates DB with site_id: A6C2BD7D1EF644D4B72C5C97D0B50B78
24+
- Rust/C opens same DB and reads site_id: (empty or different)
25+
26+
**Expected behavior:**
27+
Both implementations should read the same site_id from an existing database.
28+
29+
**Investigation Notes:**
30+
The issue might be due to missing version information in `crsql_master`. Rust/C implementation checks for a minimum version before accepting a database.
31+
32+
## Files to Modify
33+
- `zig/src/ffi/init.zig` - initialization (version writing)
34+
- `zig/src/site_identity.zig` - site_id storage/retrieval
35+
36+
## Acceptance Criteria
37+
- [x] When Rust/C opens a Zig-created DB, site_id is preserved
38+
- [x] When Zig opens a Rust/C-created DB, site_id is preserved
39+
- [x] `zig/harness/test-oracle-parity.sh` Test 4b and 4c pass
40+
41+
## Completion Notes
42+
43+
**Date:** 2025-12-20
44+
45+
**Root Cause:**
46+
When Rust/C opens a database, it checks for `crsqlite_version` in `crsql_master`. If this key is missing, Rust/C treats the database as uninitialized and generates a new site_id, overwriting the Zig-created site_id.
47+
48+
**Fix:**
49+
Modified `zig/src/ffi/init.zig` to write `crsqlite_version|160300` to `crsql_master` during extension initialization. This matches what Rust/C expects to see in a properly initialized cr-sqlite database.
50+
51+
**Changes Made:**
52+
1. Added `CRSQLITE_VERSION_INT = 160300` constant to match Rust/C version format
53+
2. Added `writeVersionToMaster()` function to insert version on init
54+
3. Called this function after creating `crsql_master` table
55+
56+
**Test Output (oracle parity test):**
57+
```
58+
Test 4b: Cross-open Zig DB with Rust/C preserves site_id
59+
PASS: Rust/C reads Zig's site_id correctly: 2CF88A20CF754064ABA66224BF453B1A
60+
Test 4c: Cross-open Rust/C DB with Zig preserves site_id
61+
PASS: Zig reads Rust/C's site_id correctly: 45CBAA5355F24CEC9060A758300B8261
62+
```
63+
64+
**No Regressions:**
65+
The full parity test suite was run and no new failures were introduced. Existing failures are pre-existing issues unrelated to this change.

AGENTS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,9 @@ run_zig() {
174174
- Function conflicts (both register `crsql_as_crr`, etc.)
175175
- Double triggers on CRR tables
176176
- Invalid test results
177+
178+
## Temporary Files
179+
180+
**Use `.tmp/` for all temporary files, never `/tmp/`.**
181+
182+
This keeps temp files within the repo (gitignored) for easier debugging and cleanup.

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

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

3-
> Last updated: 2025-12-20 (Round 51 — TASK-121, TASK-122 complete — zero divergences)
3+
> Last updated: 2025-12-20 (Round 52 — TASK-123, TASK-124 complete — clock schema + site_id cross-open fixed)
44
55
## Status
66

@@ -13,8 +13,13 @@
1313
Goal: invalidate the hypothesis that "Zig is done" by expanding cross-implementation parity coverage and adding real-system tests.
1414

1515
### Open Gaps (Parity Divergences)
16-
- [ ] **TASK-123** — Fix clock table schema parity (pk vs key, index) `.tasks/backlog/TASK-123-fix-clock-table-schema-parity.md`
17-
- [ ] **TASK-124** — Fix site_id preservation on cross-open `.tasks/backlog/TASK-124-fix-site-id-cross-open-parity.md`
16+
- [x] **TASK-123** — Fix clock table schema parity (pk vs key, index) ✓ `.tasks/done/TASK-123-fix-clock-table-schema-parity.md`
17+
- Column renamed `pk``key`, added STRICT mode, added `_dbv_idx` index
18+
- [x] **TASK-124** — Fix site_id preservation on cross-open ✓ `.tasks/done/TASK-124-fix-site-id-cross-open-parity.md`
19+
- Added `crsqlite_version|160300` to `crsql_master` on init
20+
21+
### Remaining Divergences (from oracle-parity test)
22+
- [ ] Merge resolution (Test 3a/3b): Remote wins / site_id tiebreaker differs — needs investigation
1823

1924
### Parity/Coverage Tasks (ready to assign)
2025
- [x] **TASK-070** — Cover missing C suites: ext-data + sandbox ✓ `.tasks/done/TASK-070-zig-parity-extdata-sandbox.md`

0 commit comments

Comments
 (0)