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
18 changes: 16 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,21 @@ alignment costs. Until measured: 3×4 stands.
- **PII:** never emit German PII labels (medcare-rs leaf-rename at the
adapter is the guarantee). Word-boundary abort-guard before commit.
- **No model identifier** in any committed artifact (chat only).
- **Shell discipline:** `grep`/`sed`/`tail`/`head`/`awk` via Bash are
prohibited — use the Grep/Read/Glob tools.
- **Evidence discipline (SUPERSEDES the shell rule):** ⊘ the rule here was
*"`grep`/`sed`/`tail`/`head`/`awk` via Bash are prohibited — use the
Grep/Read/Glob tools."* That policed which Unix command is typed, not the
failure it was written for. The governing rule is now epistemic:
**SEARCH IS NAVIGATION, NEVER EVIDENCE.** A search may establish only
*"candidates are X, Y, Z"* — never what a type means, what a function
guarantees, that a consumer does not exist, who owns something, or which way
a dependency runs. `0 hits` proves nothing; a global negative needs a CLOSED,
explicitly named search space; a partial Read is not evidence for a
whole-file claim; and **a search must never be the last tool result before
an architectural conclusion.** `sed`/`head`/`tail`/`awk` stay prohibited for
SOURCE INSPECTION specifically (a numeric slice has no semantic boundary),
while limiting a non-search command's output stays fine. Full law, the
auto-deepen triggers, the paging rule and the delegation/escalation levels:
lance-graph `.claude/knowledge/FIRST-HAND-SOURCE-LAW.md`, enforced by that
repo's `PreToolUse` guard.
- **Append-only canon:** never delete a ledger entry; regrade in place;
corrections cite their pass (savant / G-pass / canon-pass).
120 changes: 120 additions & 0 deletions crates/ogar-r2il/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,31 @@ impl CallMask {
self.words.iter().map(|w| w.count_ones()).sum()
}

/// The mask's **active** words, borrowed — the zero-copy way out of this
/// carrier and into a plane-shaped consumer.
///
/// Sliced to `len.div_ceil(64)`, NOT the full [`MASK_WORDS`] inline
/// array: only `Pairs` (180 calls) fills three words; `Triples` (120) and
/// `Quads` (90) fill two, and their third word is a phantom the
/// population does not have. Handing it out would give a consumer a word
/// count that disagrees with [`len`](Self::len) — and a consumer whose
/// own complement clears the tail against a DIFFERENT word count than
/// this mask's [`not`](Self::not) does would then disagree on the
/// phantom's bits while agreeing on every real one. That is a
/// wrong-answer shape, not a wasted-word shape.
///
/// **Population identity travels with the words, never inside them.**
/// The bits alone do not say what they index: a consumer needs
/// [`len`](Self::len) (the bit count) and [`shape`](Self::shape) (the
/// index space) to read them at all. In particular these indices are
/// CALL SLOTS WITHIN ONE BODY — at most 180 — and are not row ordinals
/// of any table; a row-population consumer sharing this carrier's
/// Boolean algebra shares the algebra, not the index space.
#[must_use]
pub fn words(&self) -> &[u64] {
&self.words[..(self.len.div_ceil(64) as usize)]
}

fn zip(&self, other: &Self, f: impl Fn(u64, u64) -> u64) -> Self {
debug_assert_eq!(self.shape, other.shape, "masks of different shapes");
Self {
Expand Down Expand Up @@ -1007,4 +1032,99 @@ mod tests {
);
}
}

/// **The accessor is sliced to the POPULATION, not to the carrier.**
///
/// `MASK_WORDS` is 3 because `Pairs` (180 calls) needs three words. The
/// other two shapes do not: `Triples` is 120 calls and `Quads` is 90,
/// both two words, and their third inline word is a phantom the body
/// never had. Two-sided on purpose — the assertion that a narrow shape
/// yields FEWER words than the carrier holds is what fails if
/// `words()` is ever changed to hand out `&self.words` whole.
#[test]
fn words_is_sliced_to_the_population_not_the_carrier() {
assert_eq!(MASK_WORDS, 3, "carrier width changed; re-derive the table");

for (shape, want_words, want_len) in [
(LaneShape::Pairs, 3usize, 180u32),
(LaneShape::Triples, 2, 120),
(LaneShape::Quads, 2, 90),
] {
let m = CallMask::all(shape);
assert_eq!(m.len(), want_len, "{shape:?}: population");
assert_eq!(
m.words().len(),
want_words,
"{shape:?}: words() must span len.div_ceil(64), not MASK_WORDS"
);
assert_eq!(
m.words().len(),
(m.len().div_ceil(64)) as usize,
"{shape:?}: slice width must be derived from len, never hardcoded"
);
}

// Anti-vacuity: at least one shape must be NARROWER than the carrier,
// or the two readings agree by accident and this test proves nothing.
assert!(
CallMask::all(LaneShape::Quads).words().len() < MASK_WORDS,
"no shape is narrower than the carrier: the slice cannot be falsified"
);
}

/// `words()` is the same mask `contains` reads — bit for bit, including
/// the straddling word and the bits just under `len`.
///
/// An AGREEMENT test, not a slicing one: it reads only indices below
/// `len`, which live in the same words under either slice width, so it
/// is green whether or not the carrier is over-exposed. It falsifies a
/// wrong word index or a wrong bit order — nothing about the width.
#[test]
fn words_agrees_with_contains_bit_for_bit() {
for shape in [LaneShape::Pairs, LaneShape::Triples, LaneShape::Quads] {
let mut m = CallMask::empty(shape);
// Seeded scatter plus every boundary this shape can express: the
// word edges (63/64, 127/128) and its own last two slots.
let mut seeded = 0u32;
for i in 0..m.len() {
if i % 7 == 0 || i % 13 == 3 {
m.set(i);
seeded += 1;
}
}
for edge in [
0,
1,
62,
63,
64,
65,
126,
127,
128,
m.len() - 2,
m.len() - 1,
] {
if edge < m.len() {
m.set(edge);
}
}
assert!(seeded > 0, "{shape:?}: fixture set no bits");

let w = m.words();
for i in 0..m.len() {
let from_words = (w[(i / 64) as usize] >> (i % 64)) & 1 == 1;
assert_eq!(
m.contains(i),
from_words,
"{shape:?}: bit {i} disagrees between contains() and words()"
);
}
assert_eq!(
w.iter().map(|x| x.count_ones()).sum::<u32>(),
m.count(),
"{shape:?}: popcount over the slice must equal count()"
);
}
}
}
Loading