use std::path::Path;
use anyhow::Result;
use uuid::Uuid;
use crate::inner_socrates::intent::{IntentKind, IntentScope, ScopeLevel};
use crate::inner_socrates::storage::InnerSocratesStore;
use super::types::EditorCategory;
pub fn proposed_intent_kind(category: EditorCategory) -> IntentKind {
match category {
EditorCategory::DictionaryRichness => IntentKind::DeliberateRepetition,
EditorCategory::Tautology => IntentKind::DeliberateTautology,
EditorCategory::StyleInstability => IntentKind::VoiceInstabilityIntentional,
EditorCategory::BeliefStance => IntentKind::ProseBeliefIntentionalDistance,
_ => IntentKind::StylisticPatternDeliberate,
}
}
pub fn declare_intent(
project: &Path,
category: EditorCategory,
chapter: Option<&str>,
description: Option<&str>,
) -> Result<()> {
let store = InnerSocratesStore::open_for_project(project)?;
let scope = match chapter {
Some(c) => IntentScope::Chapter(c.to_string()),
None => IntentScope::Project,
};
let desc = description
.map(|s| s.to_string())
.unwrap_or_else(|| format!("{} is a deliberate choice here", category.label()));
store.add_intent_raw(
&Uuid::new_v4().to_string(),
&proposed_intent_kind(category),
&desc,
&scope,
&[category.id().to_string()],
ScopeLevel::Project,
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::inner_editor::intent_consult::consult;
use crate::inner_editor::types::{EditorFinding, EditorSeverity};
use crate::inner_socrates::intent::FindingContext;
fn finding(cat: EditorCategory) -> EditorFinding {
EditorFinding {
category: cat,
severity: EditorSeverity::Note,
observation: "x".into(),
observation_en: "x".into(),
evidence: None,
conditional: true,
suppressed_by: None,
}
}
#[test]
fn declared_intent_suppresses_the_category_in_scope() {
let dir = tempfile::tempdir().unwrap();
declare_intent(dir.path(), EditorCategory::Tautology, Some("ch04"), None).unwrap();
let store = InnerSocratesStore::open_for_project(dir.path()).unwrap();
let rows = store.list_intent_rows_raw().unwrap();
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].kind, "deliberate_tautology");
assert!(rows[0].coverage.iter().any(|c| c == "tautology"));
let ctx04 = FindingContext { chapter_id: Some("ch04".into()), ..Default::default() };
let (kept, supp) = consult(vec![finding(EditorCategory::Tautology)], &rows, &ctx04);
assert!(kept.is_empty());
assert_eq!(supp.len(), 1);
let ctx09 = FindingContext { chapter_id: Some("ch09".into()), ..Default::default() };
let (kept, _) = consult(vec![finding(EditorCategory::Tautology)], &rows, &ctx09);
assert_eq!(kept.len(), 1);
}
#[test]
fn category_kind_mapping_is_stable() {
assert_eq!(proposed_intent_kind(EditorCategory::DictionaryRichness).id(), "deliberate_repetition");
assert_eq!(proposed_intent_kind(EditorCategory::StyleInstability).id(), "voice_instability_intentional");
assert_eq!(proposed_intent_kind(EditorCategory::BeliefStance).id(), "prose_belief_intentional_distance");
assert_eq!(proposed_intent_kind(EditorCategory::StyleObservation).id(), "stylistic_pattern_deliberate");
}
}