Next-Task Policy Filter & Candidate Window Slicing #22
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implement the deterministic candidate selection and policy filtering engine for next-task recommendations, enforcing strict lifecycle status, commitment strength, explicit context blockers, duration window capacity, energy levels, and weekday career floor invariants before any semantic ranking or Jev evaluation occurs.
Background & Technical Rationale
When a user or agent requests recommendations for what to work on next (
life next --window 90m --energy medium), the system must not immediately delegate task selection to an LLM or semantic ranker. Doing so would risk hallucinating task properties, ignoring hard calendar deadlines, violating energy limits, or scheduling blocked work.Instead, Life applies a deterministic-first policy pipeline that filters the active candidate pool down to eligible tasks based on verifiable facts:
STATUSmust beNEEDS-ACTIONorIN-PROCESS. Tasks that areCOMPLETEDorCANCELLEDare strictly excluded.life-active,life-queued, andlife-someday.life-active. Tasks taggedlife-queuedorlife-somedayare strictly excluded from next-task consideration (docs/technical/jev.md:36).docs/technical/domain-model.md:24).life-*strength category have unknown strength and must NOT be automatically activated or scheduled without user review.BLOCKED.90m,2h,45m).X-LIFE-ESTIMATED-MINUTES.estimated_minutesis known andestimated_minutes > window_minutes, the task is strictly excluded.estimated_minutesis known andestimated_minutes <= window_minutes, the task is eligible.estimated_minutesis null or unknown, the task is RETAINED as eligible, but must be explicitly tagged withunknowns: ["estimated_minutes"]and must NEVER be described as fitting the window with certainty (Scenario W07).low,medium, orhigh.X-LIFE-ENERGY(low<medium<high).high, user hasmedium), the task is excluded.unknowns: ["energy"].career_floor_met = false, which flags tasks categorized witharea-careerfor priority in subsequent ranking.Exact Technical References & Specifications
Normative Next-Task Policy Specification
From
docs/technical/jev.md(lines 34–37):Workflow & Policy Defaults Contract
From
docs/technical/workflows.md(lines 27, 44–47):Domain Model Contract
From
docs/technical/domain-model.md(lines 22–25, 35):Verification Scenario W07
From
docs/technical/verification.md(line 21):What to Build
1.
src/domain/policy/next_task_filter.rsstatus == "COMPLETED"orstatus == "CANCELLED".categoriescontainslife-somedayorlife-queued, lackslife-active, or contains multiple conflicting strength tags (docs/technical/jev.md:36,domain-model.md:24).item.planned_startis present and in the future (item.planned_start > context.now) (docs/technical/domain-model.md:35).context.active_blockers.contains(&item.id). Record diagnostic reason"Task is blocked by linked context".item.estimated_minutes > Some(query.window_minutes): exclude task. Diagnostic:"Estimated duration (Xm) exceeds available window (Ym)".item.estimated_minutes.is_none(): retain task; record"estimated_minutes"inunknowns; record factual reason"Estimated duration unknown; not claimed to fit with certainty".item.estimated_minutes <= Some(query.window_minutes): retain task; record factual reason"Estimated duration (Xm) fits within available window (Ym)".item.energy > Some(query.energy): exclude task. Diagnostic:"Required energy (high) exceeds available energy (medium)".item.energy.is_none(): retain task; record"energy"inunknowns.item.energy <= Some(query.energy): retain task; record factual reason"Required energy matches available level".query.area_filteris provided, ensureitem.categoriescontainsformat!("area-{}", area).item.categoriescontains"area-career". Ifcontext.is_weekday && !context.career_floor_met && is_career, record factual reason"Matches unmet weekday career floor".2. Timeline Career Floor Query (
src/storage/timeline.rs)docs/technical/timeline-consistency.md:37–58):life_eventsoccurring ondatewhere:evidence_class == "user_report"kind == "work_block_outcome"json_extract(after_json, '$.qualifies_career_floor') == 1ortruejson_extract(after_json, '$.outcome') == 'completed'3. Unit & Integration Tests (
tests/policy_filter_tests.rs)life-somedayor unknown strength is excluded.--window 90m.estimated_minutes: null) is retained, has"estimated_minutes"inunknowns, and factual reasons do not assert guaranteed fit (Scenario W07).highenergy is excluded when query specifies--energy medium.area-careertasks as high priority when no qualifying outcome has been recorded for today.Acceptance Criteria
COMPLETED) and cancelled (CANCELLED) tasks are strictly excluded from candidate selection.life-someday,life-queued, or lackinglife-activeare strictly excluded (docs/technical/jev.md:36).planned_start > now) are excluded from immediate next-task eligibility.--window 90m.unknownattributes, and not claimed to fit with certainty (Scenario W07).highenergy requirement is filtered out when query specifies--energy lowor--energy medium.area-careertasks for priority ranking.Notes
active_blockersfrom recorded explicit blocker facts) does not exist yet and is tracked as a separate follow-up, so today the set is supplied by the caller (#24) or empty.day_outcomes; the 40% unscheduled reserve belongs to #25–#27.Cargo.tomlauthors chore lands with #35.Blocked by
Issue #022: Next-Task Policy Filter & Candidate Window Slicingto Next-Task Policy Filter & Candidate Window Slicing