feat: update README and documentation for new tools and features
- Updated README.md to reflect the addition of 3 new built-in tools, bringing the total to 37. - Revised architecture documentation to indicate the increase in tool count. - Enhanced backend documentation with updated line counts for various modules. - Modified data documentation to change edit log format from JSON to JSONL. - Updated dependencies documentation to reflect version upgrades for several crates. - Improved prompts for auto-reviewer, division implementer, planner, tester, and quality reviewer to enforce stricter coding standards regarding linter bypasses. - Refactored code in various modules to improve clarity and performance, including updates to error handling and tool execution logic. - Added comprehensive tests for IPC frame serialization and deserialization.
This commit is contained in:
@@ -93,13 +93,14 @@ fn make_division_phase(
|
||||
/// context to flow through the pipeline.
|
||||
///
|
||||
/// Returns a consolidated executive summary string.
|
||||
#[allow(clippy::ref_option)]
|
||||
pub fn run_company_pipeline(
|
||||
user_request: &str,
|
||||
session_dir: &std::path::Path,
|
||||
workspaces: &[std::path::PathBuf],
|
||||
turn_events: Option<&Arc<Mutex<std::collections::VecDeque<crate::app::state::runtime::TurnEvent>>>>,
|
||||
abort_flag: &Option<Arc<AtomicBool>>,
|
||||
custom_specialists: HashMap<String, Vec<(String, String)>>,
|
||||
custom_specialists: &HashMap<String, Vec<(String, String)>>,
|
||||
) -> anyhow::Result<String> {
|
||||
let divisions = division::all_divisions();
|
||||
|
||||
@@ -179,20 +180,21 @@ pub fn run_company_pipeline(
|
||||
.map(|f| f.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(build_executive_summary(user_request, &results, &all_findings, &divisions, &custom_specialists))
|
||||
Ok(build_executive_summary(user_request, &results, &all_findings, &divisions, custom_specialists))
|
||||
}
|
||||
|
||||
/// Run a quick company pipeline that skips non-essential divisions
|
||||
/// for simple tasks. Flow: Strategy → Engineering → Quality.
|
||||
///
|
||||
/// This is for smaller tasks where security audit and full docs are overkill.
|
||||
#[allow(clippy::ref_option)]
|
||||
pub fn run_company_pipeline_quick(
|
||||
user_request: &str,
|
||||
session_dir: &std::path::Path,
|
||||
workspaces: &[std::path::PathBuf],
|
||||
turn_events: Option<&Arc<Mutex<std::collections::VecDeque<crate::app::state::runtime::TurnEvent>>>>,
|
||||
abort_flag: &Option<Arc<AtomicBool>>,
|
||||
custom_specialists: HashMap<String, Vec<(String, String)>>,
|
||||
custom_specialists: &HashMap<String, Vec<(String, String)>>,
|
||||
) -> anyhow::Result<String> {
|
||||
let divisions = division::all_divisions();
|
||||
let quick_divisions = &divisions[..3];
|
||||
@@ -252,7 +254,7 @@ pub fn run_company_pipeline_quick(
|
||||
.map(|f| f.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(build_executive_summary(user_request, &results, &all_findings, quick_divisions, &custom_specialists))
|
||||
Ok(build_executive_summary(user_request, &results, &all_findings, quick_divisions, custom_specialists))
|
||||
}
|
||||
|
||||
/// Build a compressed executive summary from pipeline results.
|
||||
@@ -277,8 +279,7 @@ fn build_executive_summary(
|
||||
let mut start_index = 0;
|
||||
for div in divisions {
|
||||
let count = custom_specialists.get(div.name)
|
||||
.map(Vec::len)
|
||||
.unwrap_or(0);
|
||||
.map_or(0, Vec::len);
|
||||
|
||||
let mut division_verdicts = Vec::new();
|
||||
for offset in 0..count {
|
||||
@@ -393,7 +394,7 @@ mod tests {
|
||||
("Custom Label".to_string(), "Custom Focus Description".to_string())
|
||||
]
|
||||
);
|
||||
let specs = make_division_specialists(div, "Test Request", &custom.get("Strategy").unwrap());
|
||||
let specs = make_division_specialists(div, "Test Request", custom.get("Strategy").unwrap());
|
||||
assert_eq!(specs.len(), 1);
|
||||
if let ScriptPrimitive::Agent(prompt) = &specs[0] {
|
||||
assert!(prompt.contains("Custom Label"));
|
||||
|
||||
+24
-26
@@ -98,7 +98,7 @@ pub type LiveStateFn = Arc<dyn Fn(String, String, AgentStatus) + Send + Sync>;
|
||||
/// a stuck stage from blocking the entire pipeline forever.
|
||||
///
|
||||
/// Return: the agent's text output, or an error on failure.
|
||||
#[allow(clippy::too_many_lines, clippy::too_many_arguments)]
|
||||
#[allow(clippy::too_many_lines, clippy::too_many_arguments, clippy::ref_option)]
|
||||
fn spawn_single_agent(
|
||||
agent_id: &str,
|
||||
agent_name: &str,
|
||||
@@ -185,7 +185,7 @@ fn spawn_single_agent(
|
||||
// Link the shared findings Arc so note_finding calls within this
|
||||
// subagent write into the same vec visible to sibling agents.
|
||||
ctx.workflow_findings = Some(findings.clone());
|
||||
ctx.abort_flag = abort_flag.clone();
|
||||
ctx.abort_flag.clone_from(abort_flag);
|
||||
|
||||
// Create an mpsc channel and drain events in a background thread.
|
||||
// The drain thread also pushes intra-division progress updates to the
|
||||
@@ -269,34 +269,30 @@ fn spawn_single_agent(
|
||||
let deadline = Duration::from_millis(timeout);
|
||||
let mut elapsed = Duration::ZERO;
|
||||
loop {
|
||||
match done_rx.recv_timeout(poll_interval) {
|
||||
Ok(r) => break r,
|
||||
Err(_) => {
|
||||
elapsed += poll_interval;
|
||||
if elapsed >= deadline {
|
||||
break Err(anyhow::anyhow!(
|
||||
"subagent '{bg_name}' timed out after {timeout}ms",
|
||||
));
|
||||
}
|
||||
if bg_abort.as_ref().is_some_and(|f| f.load(Ordering::SeqCst)) {
|
||||
break Err(anyhow::anyhow!(
|
||||
"subagent '{bg_name}' aborted by user",
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Ok(r) = done_rx.recv_timeout(poll_interval) {
|
||||
break r;
|
||||
}
|
||||
elapsed += poll_interval;
|
||||
if elapsed >= deadline {
|
||||
break Err(anyhow::anyhow!(
|
||||
"subagent '{bg_name}' timed out after {timeout}ms",
|
||||
));
|
||||
}
|
||||
if bg_abort.as_ref().is_some_and(|f| f.load(Ordering::SeqCst)) {
|
||||
break Err(anyhow::anyhow!(
|
||||
"subagent '{bg_name}' aborted by user",
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loop {
|
||||
match done_rx.recv_timeout(poll_interval) {
|
||||
Ok(r) => break r,
|
||||
Err(_) => {
|
||||
if bg_abort.as_ref().is_some_and(|f| f.load(Ordering::SeqCst)) {
|
||||
break Err(anyhow::anyhow!(
|
||||
"subagent '{bg_name}' aborted by user",
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Ok(r) = done_rx.recv_timeout(poll_interval) {
|
||||
break r;
|
||||
}
|
||||
if bg_abort.as_ref().is_some_and(|f| f.load(Ordering::SeqCst)) {
|
||||
break Err(anyhow::anyhow!(
|
||||
"subagent '{bg_name}' aborted by user",
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -358,6 +354,7 @@ type ParallelResult = (usize, anyhow::Result<Vec<String>>);
|
||||
/// Return: a `Vec<String>` of all agent outputs (or error strings) in
|
||||
/// the order they were submitted.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(clippy::ref_option, clippy::too_many_lines)]
|
||||
pub fn execute_primitive(
|
||||
primitive: &ScriptPrimitive,
|
||||
args: &HashMap<String, String>,
|
||||
@@ -529,6 +526,7 @@ pub fn run_workflow(
|
||||
/// `spawn_agents` invocations remain fully isolated.
|
||||
///
|
||||
/// Return: a human-readable summary string.
|
||||
#[allow(clippy::ref_option)]
|
||||
pub fn run_workflow_tracked(
|
||||
script: &WorkflowScript,
|
||||
args: &HashMap<String, String>,
|
||||
|
||||
Reference in New Issue
Block a user