STTP SDK Recursive Node-From-Text Composite Guide
Date: 2026-05-03 Status: Implemented (initial slice)
1. Purpose
This guide documents the recursive deterministic composition workflow in locus-sdk.
The workflow lets callers build a spec-safe STTP content-layer payload from plain text entries without requiring model summarization for the core compression path.
2. What It Solves
- Build content payloads from ordered role-tagged text input.
- Support recursive context trees while staying validator-safe.
- Resolve AVEC using explicit deterministic policy order.
- Keep an optional LLM path only for unresolved AVEC, not core compression.
3. Core Types
Defined in locus-sdk/src/application/memory_composition.rs:
- CompositeRole
- CompositeInputItem
- CompositeRoleAvecOverrides
- CompositeNodeFromTextOptions
- CompositeNodeFromTextRequest
- CompositeNodeFromTextResult
DTO equivalents are defined in locus-sdk/src/interface/dto.rs:
- CompositeRoleDto
- CompositeInputItemDto
- CompositeRoleAvecOverridesDto
- CompositeNodeFromTextOptionsDto
- CompositeNodeFromTextRequestDto
- CompositeNodeFromTextResponseDto
4. Deterministic AVEC Resolution
For each input item, AVEC resolution order is:
- item-level override (CompositeInputItem.avec_override)
- role-level override (CompositeNodeFromTextOptions.role_avec)
- global override (CompositeNodeFromTextOptions.global_avec)
- unresolved
If unresolved item count is greater than zero:
- if allow_llm_avec_fallback is false, the workflow fails with a typed error,
- if allow_llm_avec_fallback is true, requires_llm_avec is true in the result.
5. Recursion and Validation Constraints
- Requested depth is clamped to [1, 5].
- Build fails if item context exceeds max_recursion_depth.
- The content object uses confidence-scored keys to remain strict-parser compatible.
- This aligns with validator nesting limits in core validator logic.
Reference: locus-core-rs/src/application/validation/tree_sitter_validator.rs
6. Compression Strategy
Each input/context item is compressed with ManualCompressionService to derive:
- anchor_topic
- key_points
This keeps the composite deterministic and model-optional for compression.
Reference: locus-sdk/src/application/manual_compression.rs
7. Quick Example (Domain Models)
use std::sync::Arc;
use anyhow::Result;
use locus_core_rs::{InMemoryNodeStore, NodeStore};
use locus_core_rs::domain::models::AvecState;
use locus_sdk::prelude::{
CompositeInputItem, CompositeNodeFromTextOptions, CompositeNodeFromTextRequest,
CompositeRole, CompositeRoleAvecOverrides, MemoryCompositionService,
};
fn main() -> Result<()> {
let store: Arc<dyn NodeStore> = Arc::new(InMemoryNodeStore::new());
let composition = MemoryCompositionService::new(store);
let req = CompositeNodeFromTextRequest {
items: vec![CompositeInputItem {
role: CompositeRole::Conversation,
text: "user asks about fallback policy and model explains ranked retrieval".to_string(),
avec_override: None,
context: vec![CompositeInputItem {
role: CompositeRole::Document,
text: "design notes mention deterministic lexical fallback".to_string(),
avec_override: None,
context: Vec::new(),
}],
}],
options: CompositeNodeFromTextOptions {
role_avec: CompositeRoleAvecOverrides {
conversation: Some(AvecState {
stability: 0.82,
friction: 0.20,
logic: 0.86,
autonomy: 0.74,
}),
..Default::default()
},
global_avec: Some(AvecState {
stability: 0.75,
friction: 0.25,
logic: 0.80,
autonomy: 0.70,
}),
allow_llm_avec_fallback: false,
max_recursion_depth: 5,
},
};
let result = composition.build_content_from_text(&req)?;
println!("resolved_avec_count={}", result.resolved_avec_count);
println!("requires_llm_avec={}", result.requires_llm_avec);
println!("content={}", result.content);
Ok(())
}
8. Quick Example (DTO Boundary)
#![allow(unused)]
fn main() {
use locus_sdk::prelude::{
CompositeNodeFromTextRequestDto, CompositeNodeFromTextResponseDto,
};
fn convert_boundary(req_dto: CompositeNodeFromTextRequestDto) -> CompositeNodeFromTextResponseDto {
let domain_req = req_dto.into();
let domain_result = service.build_content_from_text(&domain_req).unwrap();
domain_result.into()
}
}
9. Test Coverage
Current coverage includes:
- role and global AVEC resolution chain
- unresolved AVEC failure behavior
- recursion depth enforcement
- strict parser and validator conformance for generated content payload
Reference tests: locus-sdk/src/application/memory_composition.rs
10. Integration Notes
- This workflow currently returns content-layer payload plus AVEC resolution stats.
- It does not replace typed IR grammar; it composes spec-safe content for insertion into full STTP node workflows.
- Recommended next step is a full store-ready recipe that assembles the complete four-layer node from this content payload.