Skip to main content

Planner

Struct Planner 

Source
pub struct Planner { /* private fields */ }
Expand description

A working snapshot of the planning registry, bound to a repo root.

Implementations§

Source§

impl Planner

Source

pub fn load() -> Result<Self>

Load the planning registry from tix.toml in the current directory, on the crate-wide assumption that commands run from the repo root.

Source

pub fn load_from(path: &Path) -> Result<Self>

Load the planning registry from an explicit config path.

Source

pub fn from_config(config: Config, root: PathBuf) -> Self

Build a planner from an already-loaded config (used by tix init and tests). The config is not persisted here; mutators save on demand.

Source

pub fn config(&self) -> &Config

The backing config this planner currently mirrors.

Source

pub fn category_resolution(&self) -> CategoryResolution

The resolution this planner’s board maps through.

Built here rather than stored, because a Planner is a short-lived view over a config and caching it would be the per-object rebuild the service’s “built once per config load” rule exists to avoid. The expensive part of a sweep is not building this — it is a handful of hash inserts per column — it is not re-deriving it per issue, and that is what callers do wrong.

Source

pub fn schedule_index(&self) -> Result<ScheduleIndex>

The cycle-identity index this planner’s records resolve through (issue #181).

One read of docs/cycles/ — or of the legacy [cycles.<name>] tables when there is no store, which is the loader’s own rule — through crate::capacity::schedule_index. It is the same index crate::cycle_schedule::registry::load_index builds, and the same one crate::capacity::resolve_cycle resolves a capacity scope reference against, so a caller never has to build a second one.

Source

pub fn capacity_snapshot_from(&self, issues: &[Issue]) -> Result<IssueSnapshot>

One indexed capacity snapshot over the issues a caller already read (WP02).

The cycle records are read once (Planner::schedule_index) and the issues are indexed once (IssueSnapshot::build): cycle, team, and assignee membership, #183’s completion answer, and every estimate parse and explicit conversion are resolved there, so no calculation needs to read the store or re-parse an estimate again (NFR-001). This is the entry point WP03’s calculation service reads.

Source

pub fn capacity_snapshot(&self, store: &Store) -> Result<IssueSnapshot>

Planner::capacity_snapshot_from over a store, read once here.

The store read and the index build are the only I/O a capacity calculation performs; everything a surface then asks is a lookup into the returned snapshot.

Source

pub fn milestones_dir(&self) -> PathBuf

The resolved milestones directory, relative to the repo root.

Source

pub fn team(&self, label: &str) -> Option<&Team>

Look up a team by label.

Source

pub fn cycle(&self, name: &str) -> Option<&PlanningCycle>

Look up a cycle by name.

The implicit Default cycle answers even when it has no file, so a fresh project can name it.

Source

pub fn cycle_names(&self) -> Vec<String>

Cycle names in declaration order.

The implicit Default cycle is not invented here: a project with no store shows only what it has actually configured, and the legacy tix.toml listing is preserved. CycleStore::list is where the implicit default is surfaced (the cycle mode lists through it), and Planner::cycle answers for the name regardless.

Source

pub fn is_overdue(issue: &Issue, today: &str) -> bool

Source

pub fn cycle_expired(cycle: &PlanningCycle, today: &str) -> bool

Source

pub fn is_running(cycle: &PlanningCycle, today: &str) -> bool

Whether cycle is running on today: its start_date is present and <= today, and its due_date is either absent (open-ended) or >= today. Both bounds are inclusive, so a cycle runs on its first and its last day. The implicit, date-less Default cycle has no start date and therefore never runs.

Source

pub fn running_cycle(&self, today: &str) -> Option<String>

The single cycle running on today, if exactly one is.

None when no cycle runs — there is nothing to assign — and None when two or more do, because an ambiguous date range must fall back to the configured [planning].default_cycle rather than guess which one the caller meant. See Planner::is_running for the running rule; the implicit Default cycle is never a candidate.

Source

pub fn overlapping_cycles(&self, name: &str) -> Vec<String>

Names of the cycles whose date window intersects name’s.

A cycle’s window is [start_date, due_date], both bounds inclusive; an absent due_date leaves the window open-ended, so it meets every later window. Touching endpoints intersect (the shared day is in both). A cycle with no start_date has no window: it never overlaps anything, and a name that has no start_date reports no overlaps. name is never reported against itself, and the result follows config declaration order.

Source

pub fn successor<'a>( &'a self, cycle: &str, today: &str, ) -> Option<(&'a str, &'a PlanningCycle)>

Source

pub fn overdue_batch(&self, store: &Store, today: &str) -> Vec<Issue>

Source

pub fn rollover_plan(&self, store: &Store, today: &str) -> Vec<RolloverTarget>

Source

pub fn rollover_plan_from( &self, all: &[Issue], today: &str, ) -> Vec<RolloverTarget>

Planner::rollover_plan over an already-read issue set (tix #1518).

The TUI reads the tree once at startup and hands the same slice to the board, the corpus and this plan, instead of walking the store again for every expired cycle. The result is identical to Planner::rollover_plan: the enumeration is the only thing that moved out of the loop.

Source

pub fn cycle_progress(&self, store: &Store, name: &str) -> Progress

Source

pub fn milestone_progress(&self, store: &Store, name: &str) -> Progress

Source

pub fn next_cycle_name(&mut self) -> String

The next auto cycle name. Skips forward past any existing Cycle N keys and permanently bumps [planning].cycle_number one past the returned name, per the seed’s cycle_number = 1 successor semantics. The bump is persisted by the mutator that calls this.

Source

pub fn add_cycle(&mut self, name: Option<String>) -> Result<String>

Create a named or auto cycle. An explicit name must not collide with the current auto-counter successor (Cycle {cycle_number}), a config error, so hand-authored keys and generated ones never overlap.

Source

pub fn rename_cycle(&mut self, old: &str, new: &str) -> Result<()>

Rename a cycle, moving its declaration order slot and rebasing default_cycle when it pointed at the old name.

Source

pub fn delete_impact(&self, store: &Store, name: &str) -> Result<Impact>

Source

pub fn rename_cycle_cascade( &mut self, store: &Store, old: &str, new: &str, ) -> Result<RenameImpact>

Source

pub fn set_cycle_fields( &mut self, name: &str, description: Option<&str>, start_date: Option<&str>, due_date: Option<&str>, ) -> Result<()>

Source

pub fn delete_cycle(&mut self, name: &str) -> Result<()>

Source

pub fn add_team_member(&mut self, label: &str, member: &str) -> Result<()>

Add a member to a team, creating the team when absent. Duplicate members and blank inputs are rejected.

Source

pub fn list_milestones(&self) -> Result<Vec<Milestone>>

All milestones, sorted by filename (which sorts by target_date then slug — the registry is a directory listing, never a stored list).

Source

pub fn milestone_names(&self) -> Result<Vec<String>>

Milestone names in listing order.

Source

pub fn milestone(&self, name: &str) -> Result<Milestone>

Look up a milestone by its frontmatter name.

Source

pub fn create_milestone_file( &self, name: &str, target_date: Option<&str>, description: Option<&str>, ) -> Result<PathBuf>

Create a milestone registry file. The filename is {created}-{slug}.md where created is today’s date; an optional target_date is stored in the frontmatter and must be a valid YYYY-MM-DD calendar date when given (FR-007). The markdown body is the optional description. Refuses to overwrite an existing file.

Source

pub fn rename_milestone_file( &self, old: &Milestone, new_name: &str, ) -> Result<PathBuf>

Rename a milestone file, keeping the created date prefix, bumping updated and rebasing the frontmatter name; the body is preserved verbatim (the cascade back into referencing issues is FR-009/IC-08 work that lives in the issue layer, not the registry).

Source

pub fn milestone_delete_impact( &self, store: &Store, name: &str, ) -> Result<Impact>

Source

pub fn rename_milestone_cascade( &self, store: &Store, old: &Milestone, new_name: &str, ) -> Result<RenameImpact>

Source

pub fn update_milestone( &self, name: &str, target_date: Option<&str>, description: Option<&str>, ) -> Result<()>

Source

pub fn delete_milestone(&self, name: &str) -> Result<String>

Trait Implementations§

Source§

impl Clone for Planner

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Planner

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.