Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/board/entries/2026-10-25-drf-w1-writeback.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# D-DRF W1–W3 — staged writeback coalesced per canonical row (lab)
# D-DRF-W1 — W1–W3: staged writeback coalesced per canonical row (lab)

**Status:** TEST-PINNED (lab). **Code:** `crates/drf-focus-probe/src/lib.rs` (`Focus::writeback`,
`Writeback::{stage, dirty_rows, flush}`, `RowImage`). **Tests:** `w1_*`, `w2_*`, `w3_*` in
Expand Down
19 changes: 19 additions & 0 deletions .claude/board/entries/2026-10-25-drf-w3-ordered-apply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# D-DRF-W3 — ordered same-facet writes apply by declared stream position (lab)

**Status:** TEST-PINNED (lab). **Code:** `crates/drf-focus-probe/src/lib.rs`
(`Writeback::stage_at`, `flush`). **Tests:** `tests/integration/focus.rs`
`w3_ordered_*`, `w3_equal_positions_or_mixed_ordering_*`. Plan:
`.claude/plans/d-dr64-focus-cache-falsifiers-v1.md` §4 W3.

- **W3 PASS (ordered arm):** three noncommuting overwrites of one facet (positions 1, 2, 3)
through three aliasing slots give the position-3 value in all 6 staging orders. 64 writes
over 4 rows in a scrambled staging order match a scalar oracle (highest position per row).
- **W3 PASS (refusal arm):** different values at one declared position, or an unordered
`stage` next to a positioned one, refuse with `Conflict`. Equal values coalesce in both.
- **Mechanism:** patches sort by `(ord, offset, pos)` and apply in that order, so the
sort is the order of application; no second pass.
- **Disables, each red on its own test:** sort without `pos` (staging order wins); treat
equal positions as ordered; treat an unordered write as ordered.

OPEN: positions are caller-declared `u64`s. Nothing yet ties them to a real stream
(CycleWriter sequence, WAL LSN); that is W4–W6.
5 changes: 3 additions & 2 deletions .claude/board/entries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately
opposite directions; the stranding this convention prevents shows up in
exactly one of them, never both.

467 entries, 2026-08-06 .. 2026-10-25.
468 entries, 2026-08-06 .. 2026-10-25.

| date | entry id | finding | file |
|---|---|---|---|
| 2026-10-25 | `D-DRF` | | [2026-10-25-drf-w1-writeback.md](2026-10-25-drf-w1-writeback.md) |
| 2026-10-25 | `D-DRF-W3` | | [2026-10-25-drf-w3-ordered-apply.md](2026-10-25-drf-w3-ordered-apply.md) |
| 2026-10-25 | `D-DRF-W1` | | [2026-10-25-drf-w1-writeback.md](2026-10-25-drf-w1-writeback.md) |
| 2026-10-24 | `tanh-precision-symmetric-i8` | | [2026-10-24-tanh-precision-symmetric-i8.md](2026-10-24-tanh-precision-symmetric-i8.md) |
| 2026-10-24 | `D-DRF-P2` | | [2026-10-24-drf-p2-breakeven.md](2026-10-24-drf-p2-breakeven.md) |
| 2026-10-24 | `D-DRF-P1` | | [2026-10-24-drf-p1-focus-lease-probe.md](2026-10-24-drf-p1-focus-lease-probe.md) |
Expand Down
48 changes: 40 additions & 8 deletions crates/drf-focus-probe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ struct Patch {
ord: u16,
offset: usize,
value: i32,
/// Declared stream position. `None` sorts before every `Some`, so an
/// unordered write is applied first and can only coexist with ordered
/// writes of the same value (checked in `flush`).
pos: Option<u64>,
}

/// The final image of one dirty canonical row, owned for handoff to a writer.
Expand All @@ -319,8 +323,32 @@ impl Focus {
}

impl Writeback<'_> {
/// Stage `value` into `facet` of the row behind `slot`.
/// Stage `value` into `facet` of the row behind `slot`, with no declared
/// order: a second write to the same facet must carry the same value.
pub fn stage(&mut self, slot: usize, facet: Facet, value: i32) -> Result<(), Refusal> {
self.push(slot, facet, value, None)
}

/// Stage `value` at declared stream position `pos`. Writes to one facet
/// apply in position order whatever order they were staged in; two
/// different values at one position refuse (W3).
pub fn stage_at(
&mut self,
slot: usize,
facet: Facet,
value: i32,
pos: u64,
) -> Result<(), Refusal> {
self.push(slot, facet, value, Some(pos))
}

fn push(
&mut self,
slot: usize,
facet: Facet,
value: i32,
pos: Option<u64>,
) -> Result<(), Refusal> {
let ord = *self
.focus
.map
Expand All @@ -331,6 +359,7 @@ impl Writeback<'_> {
ord,
offset: facet.offset(),
value,
pos,
});
Ok(())
}
Expand All @@ -345,8 +374,9 @@ impl Writeback<'_> {

/// One image per distinct dirty row, in ordinal order: the sealed source row
/// with every staged facet applied. Writes to different facets of one row
/// all survive (W2); two different values for the same facet, or two
/// facets whose byte ranges overlap, refuse (W3).
/// all survive (W2). Writes to one facet apply in declared position
/// order; different values with no order between them (equal positions,
/// or an unordered write), or facets whose byte ranges overlap, refuse (W3).
pub fn flush(mut self, soa: &Soa<'_>) -> Result<Vec<RowImage>, Refusal> {
check_seal(soa, &self.focus.map)?;
if self.focus.key.source != soa.id {
Expand All @@ -355,16 +385,17 @@ impl Writeback<'_> {
source_seal: soa.id.index_seal,
});
}
self.patches.sort_by_key(|p| (p.ord, p.offset));
self.patches.sort_by_key(|p| (p.ord, p.offset, p.pos));
for w in self.patches.windows(2) {
if w[0].ord != w[1].ord {
continue;
}
// Same facet with a different value, or two facets whose byte
// ranges overlap: either would silently overwrite a staged write.
// Sorted by offset, so checking neighbours finds every overlap.
// Same facet: different values need two distinct declared
// positions, else nothing says which wins. Different facets must
// not overlap. Sorted by offset, so neighbours find every overlap.
let same = w[0].offset == w[1].offset;
if (same && w[0].value != w[1].value)
let ordered = matches!((w[0].pos, w[1].pos), (Some(a), Some(b)) if a != b);
if (same && w[0].value != w[1].value && !ordered)
Comment thread
AdaWorldAPI marked this conversation as resolved.
|| (!same && w[1].offset < w[0].offset + Facet::WIDTH)
{
return Err(Refusal::Conflict {
Expand All @@ -373,6 +404,7 @@ impl Writeback<'_> {
});
}
}
// Applying in sorted order leaves each facet at its highest position.
let mut out: Vec<RowImage> = Vec::new();
for p in &self.patches {
if out.last().is_none_or(|img| img.ord != p.ord) {
Expand Down
96 changes: 96 additions & 0 deletions crates/drf-focus-probe/tests/integration/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,3 +490,99 @@ fn w3_overlapping_facets_at_different_offsets_refuse_and_adjacent_facets_both_su
assert_eq!(row[OFF..OFF + 4], 1i32.to_le_bytes());
assert_eq!(row[OFF + 4..OFF + 8], 2i32.to_le_bytes());
}

#[test]
fn w3_ordered_same_facet_writes_apply_by_declared_position_in_every_staging_order() {
// Two slots alias row 500. The writes do not commute (overwrite), so the
// result must follow the declared stream position, not the staging order.
let r = rows();
let soa = Soa {
rows: &r,
id: sid(1, 1, 1, 9),
};
let m = map_from(304, 9, |s| if s < 3 { 500 } else { (s % NROWS) as u16 });
let mgr = FocusManager::new();
let f = mgr.load(&soa, &m, Scope(1), facet()).unwrap();
let writes = [(0usize, 30i32, 3u64), (1, 10, 1), (2, 20, 2)];
let perms = [
[0, 1, 2],
[0, 2, 1],
[1, 0, 2],
[1, 2, 0],
[2, 0, 1],
[2, 1, 0],
];
for perm in perms {
let mut wb = f.writeback();
for i in perm {
let (slot, value, pos) = writes[i];
wb.stage_at(slot, facet(), value, pos).unwrap();
}
let imgs = wb.flush(&soa).unwrap();
assert_eq!(imgs.len(), 1);
assert_eq!(
imgs[0].row[OFF..OFF + 4],
30i32.to_le_bytes(),
"order {perm:?}"
);
}
// 64 positioned writes over 4 rows in a scrambled staging order: each row
// ends with the value of its highest declared position (scalar oracle).
let m = map_from(305, 9, |s| [10u16, 20, 30, 40][s % 4]);
let f = mgr.load(&soa, &m, Scope(1), facet()).unwrap();
let mut wb = f.writeback();
let mut want = [(0u64, 0i32); 4];
for k in 0..64usize {
let slot = (k * 37) % 64;
let pos = ((k * 23) % 64) as u64;
let value = (k as i32) * 7 - 100;
wb.stage_at(slot, facet(), value, pos).unwrap();
if pos >= want[slot % 4].0 {
want[slot % 4] = (pos, value);
}
}
let imgs = wb.flush(&soa).unwrap();
assert_eq!(imgs.len(), 4);
for (i, img) in imgs.iter().enumerate() {
assert_eq!(img.ord, [10u16, 20, 30, 40][i]);
assert_eq!(img.row[OFF..OFF + 4], want[i].1.to_le_bytes());
}
}

#[test]
fn w3_equal_positions_or_mixed_ordering_with_different_values_refuse() {
let r = rows();
let soa = Soa {
rows: &r,
id: sid(1, 1, 1, 9),
};
let m = map_from(306, 9, |s| if s < 2 { 500 } else { (s % NROWS) as u16 });
let mgr = FocusManager::new();
let f = mgr.load(&soa, &m, Scope(1), facet()).unwrap();
let conflict = Some(Refusal::Conflict {
ord: 500,
offset: OFF,
});
// Same declared position, different values: no order to apply them in.
let mut wb = f.writeback();
wb.stage_at(0, facet(), 1, 5).unwrap();
wb.stage_at(1, facet(), 2, 5).unwrap();
assert_eq!(wb.flush(&soa).err(), conflict);
// An unordered write next to an ordered one, different values.
let mut wb = f.writeback();
wb.stage(0, facet(), 1).unwrap();
wb.stage_at(1, facet(), 2, 5).unwrap();
assert_eq!(wb.flush(&soa).err(), conflict);
// Silence twins: equal values coalesce in both cases.
let mut wb = f.writeback();
wb.stage_at(0, facet(), 4, 5).unwrap();
wb.stage_at(1, facet(), 4, 5).unwrap();
assert_eq!(wb.flush(&soa).unwrap().len(), 1);
let mut wb = f.writeback();
wb.stage(0, facet(), 4).unwrap();
wb.stage_at(1, facet(), 4, 9).unwrap();
assert_eq!(
wb.flush(&soa).unwrap()[0].row[OFF..OFF + 4],
4i32.to_le_bytes()
);
}
Loading