feat: add vapora-doc-lifecycle adapter for documentation management

- Create VAPORA adapter for doc-lifecycle-core integration
- DocLifecyclePlugin: Main plugin interface for orchestration
- DocumenterIntegration: Integrates with Documenter agent
- Configuration for VAPORA-specific settings

Features:
- Event-driven documentation processing (NATS)
- Automatic classification and consolidation
- RAG index generation with SurrealDB
- mdBook site generation
- Root files management (README, CHANGELOG, ROADMAP)

Dependency structure:
- Development: local path to doc-lifecycle-core
- Production: will use crates.io version

This enables gradual adoption:
1. Use standalone tool in any Rust project
2. Integrate into VAPORA for automatic processing
3. Share core library between both deployments
This commit is contained in:
Jesús Pérez 2025-11-10 18:13:38 +00:00
parent ca3fa91d5d
commit 5ea9e3f4de
6 changed files with 291 additions and 0 deletions

View File

@ -0,0 +1,23 @@
[package]
name = "vapora-doc-lifecycle"
version = "0.1.0"
edition = "2021"
authors = ["Jesus Perez <jesus@jesusperez.pro>"]
license = "MIT"
description = "VAPORA adapter for documentation lifecycle management"
[dependencies]
doc-lifecycle-core = { path = "../../../Tools/doc-lifecycle-manager/crates/doc-lifecycle-core" }
tokio = { version = "1.35", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tracing = "0.1"
anyhow = "1.0"
thiserror = "1.0"
# VAPORA dependencies (will be added later)
# vapora-shared = { path = "../vapora-shared" }
# vapora-agents = { path = "../vapora-agents" }
[dev-dependencies]
tempfile = "3.8"

View File

@ -0,0 +1,55 @@
//! Configuration for doc-lifecycle VAPORA adapter
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
/// Plugin configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginConfig {
/// Enable doc-lifecycle plugin
pub enabled: bool,
/// Root directory for documentation
pub docs_root: PathBuf,
/// Mode: minimal, standard, or full
pub mode: String,
/// Classify on task completion
pub auto_classify: bool,
/// Consolidate duplicates automatically
pub auto_consolidate: bool,
/// Generate RAG index
pub generate_rag_index: bool,
/// Generate mdBook site
pub generate_mdbook: bool,
/// Language for documentation
pub language: String,
/// NATS subject for task events
pub nats_subject: String,
/// SurrealDB connection string
pub surreal_url: String,
}
impl Default for PluginConfig {
fn default() -> Self {
Self {
enabled: true,
docs_root: PathBuf::from("docs"),
mode: "standard".to_string(),
auto_classify: true,
auto_consolidate: true,
generate_rag_index: true,
generate_mdbook: true,
language: "en".to_string(),
nats_subject: "vapora.tasks.completed".to_string(),
surreal_url: "surreal://localhost:8000".to_string(),
}
}
}

View File

@ -0,0 +1,56 @@
//! Documenter agent integration with doc-lifecycle
use crate::config::PluginConfig;
use crate::plugin::DocLifecyclePlugin;
use crate::Result;
/// Documenter agent integration
#[derive(Debug)]
pub struct DocumenterIntegration {
plugin: DocLifecyclePlugin,
config: PluginConfig,
}
impl DocumenterIntegration {
/// Create a new documenter integration
pub fn new(config: PluginConfig) -> Result<Self> {
let plugin = DocLifecyclePlugin::new(config.clone())?;
Ok(Self { plugin, config })
}
/// Handle task completion event
pub async fn on_task_completed(&mut self, task_id: &str) -> Result<()> {
tracing::info!(
"Documenter: Processing task completion for task {}",
task_id
);
// 1. Process documentation
self.plugin.process_task_docs(task_id).await?;
// 2. Update root files (README, CHANGELOG, ROADMAP)
self.update_root_files(task_id).await?;
// 3. Publish event for other agents
self.publish_docs_updated_event(task_id).await?;
Ok(())
}
async fn update_root_files(&self, _task_id: &str) -> Result<()> {
// TODO: Update README, CHANGELOG, ROADMAP
Ok(())
}
async fn publish_docs_updated_event(&self, _task_id: &str) -> Result<()> {
// TODO: Publish to NATS
Ok(())
}
/// Get current configuration
#[must_use]
pub fn config(&self) -> &PluginConfig {
&self.config
}
}

View File

@ -0,0 +1,41 @@
//! Error types for VAPORA doc-lifecycle adapter
use std::fmt;
/// Result type for adapter operations
pub type Result<T> = std::result::Result<T, Error>;
/// Error type for adapter operations
#[derive(Debug)]
pub enum Error {
/// Core library error
Core(doc_lifecycle_core::Error),
/// Configuration error
Config(String),
/// NATS error
NatsError(String),
/// Database error
DatabaseError(String),
/// Other errors
Other(Box<dyn std::error::Error + Send + Sync>),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Core(e) => write!(f, "Core error: {}", e),
Self::Config(msg) => write!(f, "Config error: {}", msg),
Self::NatsError(msg) => write!(f, "NATS error: {}", msg),
Self::DatabaseError(msg) => write!(f, "Database error: {}", msg),
Self::Other(e) => write!(f, "{}", e),
}
}
}
impl std::error::Error for Error {}
impl From<doc_lifecycle_core::Error> for Error {
fn from(err: doc_lifecycle_core::Error) -> Self {
Self::Core(err)
}
}

View File

@ -0,0 +1,28 @@
//! VAPORA Documentation Lifecycle Management Adapter
//!
//! This crate provides integration between VAPORA's agent orchestration
//! and the doc-lifecycle-core library.
//!
//! Features:
//! - Event-driven documentation processing
//! - NATS JetStream integration for task events
//! - SurrealDB vector store for RAG indexing
//! - Automatic triggering on task completion
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
pub mod plugin;
pub mod documenter;
pub mod config;
pub mod error;
pub use error::{Error, Result};
/// Re-export commonly used types
pub mod prelude {
pub use crate::plugin::DocLifecyclePlugin;
pub use crate::documenter::DocumenterIntegration;
pub use crate::config::PluginConfig;
pub use crate::{Error, Result};
}

View File

@ -0,0 +1,88 @@
//! Doc-lifecycle plugin for VAPORA
use crate::config::PluginConfig;
use crate::Result;
use doc_lifecycle_core::prelude::*;
use std::path::PathBuf;
/// Main plugin interface for doc-lifecycle integration
#[derive(Debug)]
pub struct DocLifecyclePlugin {
config: PluginConfig,
classifier: Classifier,
consolidator: Consolidator,
rag_indexer: RagIndexer,
mdbook_generator: Option<MdBookGenerator>,
}
impl DocLifecyclePlugin {
/// Create a new doc-lifecycle plugin
pub fn new(config: PluginConfig) -> Result<Self> {
let mdbook_generator = if config.generate_mdbook {
let mdbook_config = doc_lifecycle_core::mdbook_generator::MdBookConfig::new(
PathBuf::from("book"),
"VAPORA Project".to_string(),
);
Some(MdBookGenerator::new(mdbook_config))
} else {
None
};
Ok(Self {
config,
classifier: Classifier::new(),
consolidator: Consolidator::new(),
rag_indexer: RagIndexer::new(),
mdbook_generator,
})
}
/// Process documentation for a completed task
pub async fn process_task_docs(&mut self, task_id: &str) -> Result<()> {
tracing::info!("Processing task docs for task {}", task_id);
// 1. Classify documents
if self.config.auto_classify {
self.classify_session_docs(task_id).await?;
}
// 2. Consolidate duplicates
if self.config.auto_consolidate {
self.consolidate_docs().await?;
}
// 3. Generate RAG index
if self.config.generate_rag_index {
self.update_rag_index().await?;
}
// 4. Generate mdBook
if self.config.generate_mdbook {
self.generate_mdbook().await?;
}
Ok(())
}
async fn classify_session_docs(&self, _task_id: &str) -> Result<()> {
// TODO: Implement session doc classification
Ok(())
}
async fn consolidate_docs(&self) -> Result<()> {
// TODO: Implement consolidation
Ok(())
}
async fn update_rag_index(&self) -> Result<()> {
// TODO: Implement RAG index update
Ok(())
}
async fn generate_mdbook(&self) -> Result<()> {
if let Some(generator) = &self.mdbook_generator {
generator.generate()?;
}
Ok(())
}
}