diff --git a/.omo/boulder.json b/.omo/boulder.json index 0c611a3..602bb49 100644 --- a/.omo/boulder.json +++ b/.omo/boulder.json @@ -8,7 +8,7 @@ "plan_name": "phase1-wal", "status": "active", "started_at": "2026-06-12T05:09:32.588Z", - "updated_at": "2026-06-12T06:20:06.478Z", + "updated_at": "2026-06-12T06:29:05.569Z", "session_ids": [ "opencode:ses_145c3bae9ffeTB2zbsTym0Cev8" ], @@ -146,6 +146,47 @@ "status": "completed", "ended_at": "2026-06-12T06:20:06.478Z", "elapsed_ms": 85727 + }, + "final-wave:f1": { + "task_key": "final-wave:f1", + "task_label": "F1", + "task_title": "**Plan Compliance Audit** — `oracle`", + "session_id": "opencode:ses_1457cb69affe9rYiUhKWDB2kDd", + "agent": "Sisyphus-Junior", + "category": "unspecified-high", + "started_at": "2026-06-12T06:23:49.269Z", + "status": "running", + "updated_at": "2026-06-12T06:29:05.572Z" + }, + "final-wave:f3": { + "task_key": "final-wave:f3", + "task_label": "F3", + "task_title": "Real Manual QA — execute all QA scenarios from the plan and verify cross-module integration.", + "session_id": "opencode:ses_1458206c0ffeyx0AQoGlHap1Wb", + "agent": "oracle", + "updated_at": "2026-06-12T06:23:50.560Z", + "started_at": "2026-06-12T06:23:50.560Z", + "status": "running" + }, + "final-wave:f2": { + "task_key": "final-wave:f2", + "task_label": "F2", + "task_title": "Code Quality Review — run static analysis and review all .go files for quality issues.", + "session_id": "opencode:ses_145823a08ffeN5NdqAbplhAFfu", + "agent": "oracle", + "updated_at": "2026-06-12T06:23:51.328Z", + "started_at": "2026-06-12T06:23:51.328Z", + "status": "running" + }, + "final-wave:f4": { + "task_key": "final-wave:f4", + "task_label": "F4", + "task_title": "Scope Fidelity Check — verify each task's implementation matches its spec with no scope creep.", + "session_id": "opencode:ses_14581c42cffeKPlQGJV5yvUNk5", + "agent": "oracle", + "updated_at": "2026-06-12T06:24:29.653Z", + "started_at": "2026-06-12T06:24:29.653Z", + "status": "running" } } } @@ -153,7 +194,7 @@ "active_plan": "/home/dailz/workspace/src/go-kv/.omo/plans/phase1-wal.md", "started_at": "2026-06-12T05:09:32.588Z", "status": "active", - "updated_at": "2026-06-12T06:20:06.478Z", + "updated_at": "2026-06-12T06:29:05.569Z", "session_ids": [ "opencode:ses_145c3bae9ffeTB2zbsTym0Cev8" ], @@ -291,6 +332,47 @@ "status": "completed", "ended_at": "2026-06-12T06:20:06.478Z", "elapsed_ms": 85727 + }, + "final-wave:f1": { + "task_key": "final-wave:f1", + "task_label": "F1", + "task_title": "**Plan Compliance Audit** — `oracle`", + "session_id": "opencode:ses_1457cb69affe9rYiUhKWDB2kDd", + "agent": "Sisyphus-Junior", + "category": "unspecified-high", + "started_at": "2026-06-12T06:23:49.269Z", + "status": "running", + "updated_at": "2026-06-12T06:29:05.572Z" + }, + "final-wave:f3": { + "task_key": "final-wave:f3", + "task_label": "F3", + "task_title": "Real Manual QA — execute all QA scenarios from the plan and verify cross-module integration.", + "session_id": "opencode:ses_1458206c0ffeyx0AQoGlHap1Wb", + "agent": "oracle", + "updated_at": "2026-06-12T06:23:50.560Z", + "started_at": "2026-06-12T06:23:50.560Z", + "status": "running" + }, + "final-wave:f2": { + "task_key": "final-wave:f2", + "task_label": "F2", + "task_title": "Code Quality Review — run static analysis and review all .go files for quality issues.", + "session_id": "opencode:ses_145823a08ffeN5NdqAbplhAFfu", + "agent": "oracle", + "updated_at": "2026-06-12T06:23:51.328Z", + "started_at": "2026-06-12T06:23:51.328Z", + "status": "running" + }, + "final-wave:f4": { + "task_key": "final-wave:f4", + "task_label": "F4", + "task_title": "Scope Fidelity Check — verify each task's implementation matches its spec with no scope creep.", + "session_id": "opencode:ses_14581c42cffeKPlQGJV5yvUNk5", + "agent": "oracle", + "updated_at": "2026-06-12T06:24:29.653Z", + "started_at": "2026-06-12T06:24:29.653Z", + "status": "running" } }, "agent": "atlas" diff --git a/memtable/memtable.go b/memtable/memtable.go index d96f1a0..7be8ff2 100644 --- a/memtable/memtable.go +++ b/memtable/memtable.go @@ -2,6 +2,7 @@ package memtable import ( "errors" + "fmt" "sync" "sync/atomic" ) @@ -114,7 +115,11 @@ func (mt *MemTable) Publish(upToSequence uint64) { // Re-put each entry as published. Each call acquires the skiplist mutex. for _, e := range toPublish { - _ = mt.skiplist.Put(e.key, e.value, e.sequence, false) + if err := mt.skiplist.Put(e.key, e.value, e.sequence, false); err != nil { + // Reserve guaranteed space, so this should never happen. + // If it does, it's an internal invariant violation. + panic(fmt.Sprintf("memtable: Put failed after Reserve: %v", err)) + } } // Update high-water mark after all entries are visible. diff --git a/wal/recover.go b/wal/recover.go index b370076..ec05bae 100644 --- a/wal/recover.go +++ b/wal/recover.go @@ -183,7 +183,7 @@ func findValidOffset(filePath string) (int64, error) { break } - rec, consumed, err := DecodePhysicalRecord(blockData[pos:]) + _, consumed, err := DecodePhysicalRecord(blockData[pos:]) if err != nil { // Corruption starts here — offset is up to last valid record. validOffset = blockStartOffset + int64(pos) @@ -192,8 +192,6 @@ func findValidOffset(filePath string) (int64, error) { // Valid record found. validOffset = blockStartOffset + int64(pos+consumed) - // Keep the rec reference alive so the compiler doesn't optimize it away. - _ = rec pos += consumed } diff --git a/wal/segment_writer.go b/wal/segment_writer.go index 34287fd..d0ad47e 100644 --- a/wal/segment_writer.go +++ b/wal/segment_writer.go @@ -19,7 +19,6 @@ type SegmentWriter struct { startSequence uint64 blockWriter *BlockWriter currentOffset uint64 // total bytes written (starts at WalFileHeaderSize) - maxPayload uint64 // cfg.MaxSegmentSize - WalFileHeaderSize } // NewSegmentWriter creates a new WAL segment file and writes the file header. @@ -89,8 +88,6 @@ func NewSegmentWriter( dirFD.Close() } - maxPayload := cfg.MaxSegmentSize - WalFileHeaderSize - return &SegmentWriter{ fd: fd, dir: dir, @@ -99,7 +96,6 @@ func NewSegmentWriter( startSequence: startSequence, blockWriter: NewBlockWriter(), currentOffset: WalFileHeaderSize, - maxPayload: maxPayload, }, nil } @@ -133,6 +129,9 @@ func (sw *SegmentWriter) AppendBatch(encodedBatch []byte) error { // Sync flushes the segment file to durable storage. func (sw *SegmentWriter) Sync() error { + if err := sw.blockWriter.Flush(sw.fd); err != nil { + return fmt.Errorf("wal: flushing partial block before sync: %w", err) + } return sw.fd.Sync() } diff --git a/wal/writer.go b/wal/writer.go index ca79047..aee496f 100644 --- a/wal/writer.go +++ b/wal/writer.go @@ -145,6 +145,12 @@ func (ww *WalWriter) processBatch(requests []*CommitRequest) { return } + // Pre-validate encoding can succeed before sequence allocation. + if _, err := EncodeWalBatch(0, entries); err != nil { + ww.sendError(requests, err) + return + } + baseSequence, err := ww.seqManager.AllocateBatch(uint32(len(entries))) if err != nil { ww.sendError(requests, err)