Skip to main content

apm/cmd/
next.rs

1use anyhow::Result;
2use apm_core::{config::Config, ticket};
3use std::path::Path;
4
5pub fn run(root: &Path, json: bool, no_aggressive: bool) -> Result<()> {
6    let config = Config::load(root)?;
7    let aggressive = config.sync.aggressive && !no_aggressive;
8
9    crate::util::fetch_if_aggressive(root, aggressive);
10
11    let tickets = ticket::load_all_from_git(root, &config.tickets.dir)?;
12    let actionable_owned = config.actionable_states_for("agent");
13    let actionable: Vec<&str> = actionable_owned.iter().map(|s| s.as_str()).collect();
14    let p = &config.workflow.prioritization;
15    let caller_name = apm_core::config::resolve_caller_name();
16    let current_user = apm_core::config::resolve_identity(root);
17
18    match ticket::pick_next(&tickets, &actionable, &[], p.priority_weight, p.effort_weight, p.risk_weight, &config, Some(&caller_name), Some(&current_user)) {
19        None => {
20            if json {
21                println!("null");
22            } else {
23                println!("No actionable tickets.");
24            }
25        }
26        Some(t) => {
27            let fm = &t.frontmatter;
28            if json {
29                println!(
30                    r#"{{"id":{:?}, "title":{:?}, "state":{:?}, "score":{}}}"#,
31                    fm.id, fm.title, fm.state, t.score(p.priority_weight, p.effort_weight, p.risk_weight)
32                );
33            } else {
34                println!("{} [{}] {}", fm.id, fm.state, fm.title);
35                if let Some(epic_id) = fm.epic.as_deref() {
36                    if let Some(epic_branch) = apm_core::epic::find_epic_branch(root, epic_id) {
37                        let s = apm_core::epic::merge_tree_status(root, &config.project.default_branch, &epic_branch)
38                            .unwrap_or(apm_core::epic::MergeStatus { ahead: 0, clean: true });
39                        let label = if s.ahead == 0 {
40                            "up to date".to_string()
41                        } else if s.clean {
42                            format!("↓{} clean", s.ahead)
43                        } else {
44                            format!("↓{} CONFLICTS", s.ahead)
45                        };
46                        println!("  (epic {epic_id}: {label})");
47                    }
48                }
49            }
50        }
51    }
52    Ok(())
53}