#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChunkClassification {
Dna = 0b00,
Context = 0b01,
Pointer = 0b10,
Reserved = 0b11,
}
impl ChunkClassification {
pub const fn bits(&self) -> u32 {
*self as u32
}
pub fn from_bits(bits: u32) -> Self {
match bits & 0b11 {
0b00 => Self::Dna,
0b01 => Self::Context,
0b10 => Self::Pointer,
_ => Self::Reserved,
}
}
pub const fn name(&self) -> &'static str {
match self {
Self::Dna => "DNA",
Self::Context => "Context",
Self::Pointer => "Pointer",
Self::Reserved => "Reserved",
}
}
}
pub const CLASSIFICATION_MASK: u32 = 0b11;
#[derive(Debug, Clone, Copy)]
pub struct CanonicalChunk {
pub name: &'static str,
pub classification: ChunkClassification,
pub priority: u8,
}
pub const CANONICAL_CHUNKS: &[CanonicalChunk] = &[
CanonicalChunk {
name: "faf_version",
classification: ChunkClassification::Dna,
priority: 255,
},
CanonicalChunk {
name: "project",
classification: ChunkClassification::Dna,
priority: 255,
},
CanonicalChunk {
name: "app_type",
classification: ChunkClassification::Dna,
priority: 200,
},
CanonicalChunk {
name: "about",
classification: ChunkClassification::Dna,
priority: 150,
},
CanonicalChunk {
name: "stack",
classification: ChunkClassification::Dna,
priority: 200,
},
CanonicalChunk {
name: "human_context",
classification: ChunkClassification::Dna,
priority: 200,
},
CanonicalChunk {
name: "tech_stack",
classification: ChunkClassification::Dna,
priority: 200,
},
CanonicalChunk {
name: "key_files",
classification: ChunkClassification::Dna,
priority: 200,
},
CanonicalChunk {
name: "commands",
classification: ChunkClassification::Dna,
priority: 180,
},
CanonicalChunk {
name: "monorepo",
classification: ChunkClassification::Dna,
priority: 150,
},
CanonicalChunk {
name: "architecture",
classification: ChunkClassification::Dna,
priority: 128,
},
CanonicalChunk {
name: "scores",
classification: ChunkClassification::Context,
priority: 64,
},
CanonicalChunk {
name: "context",
classification: ChunkClassification::Context,
priority: 64,
},
];
pub fn canonical_chunk(name: &str) -> Option<&'static CanonicalChunk> {
CANONICAL_CHUNKS.iter().find(|c| c.name == name)
}
pub fn is_canonical(name: &str) -> bool {
canonical_chunk(name).is_some()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn table_is_closed_at_13() {
assert_eq!(CANONICAL_CHUNKS.len(), 13);
let dna = CANONICAL_CHUNKS
.iter()
.filter(|c| c.classification == ChunkClassification::Dna)
.count();
let ctx = CANONICAL_CHUNKS
.iter()
.filter(|c| c.classification == ChunkClassification::Context)
.count();
assert_eq!(dna, 11);
assert_eq!(ctx, 2);
}
#[test]
fn mirrors_faf_cli_fafdata() {
for key in [
"faf_version",
"project",
"app_type",
"about",
"stack",
"human_context",
"monorepo",
"scores",
"tech_stack",
"key_files",
"commands",
"architecture",
"context",
] {
assert!(is_canonical(key), "FafData key '{}' must be canonical", key);
}
for key in [
"instant_context",
"ai_score",
"ai_confidence",
"ai_tldr",
"context_quality",
"preferences",
"state",
"tags",
"meta",
"bi_sync",
"docs",
"generated",
] {
assert!(!is_canonical(key), "'{}' must fold, not be a chunk", key);
}
}
#[test]
fn names_are_unique() {
for (i, a) in CANONICAL_CHUNKS.iter().enumerate() {
for b in &CANONICAL_CHUNKS[i + 1..] {
assert_ne!(a.name, b.name);
}
}
}
#[test]
fn identity_chunks_are_critical() {
assert_eq!(canonical_chunk("faf_version").unwrap().priority, 255);
assert_eq!(canonical_chunk("project").unwrap().priority, 255);
}
#[test]
fn context_is_the_fold_target() {
assert_eq!(
canonical_chunk("context").unwrap().classification,
ChunkClassification::Context
);
assert!(
!CANONICAL_CHUNKS
.iter()
.any(|c| c.classification == ChunkClassification::Pointer)
);
}
#[test]
fn unknown_keys_are_not_canonical() {
assert!(!is_canonical("custom_field"));
assert!(!is_canonical("my_exotic_field"));
assert!(!is_canonical("Project"));
assert!(is_canonical("project"));
}
#[test]
fn classification_bits_roundtrip() {
for class in &[
ChunkClassification::Dna,
ChunkClassification::Context,
ChunkClassification::Pointer,
ChunkClassification::Reserved,
] {
assert_eq!(ChunkClassification::from_bits(class.bits()), *class);
}
assert_eq!(
ChunkClassification::from_bits(0xFF00_0001),
ChunkClassification::Context
);
}
}