feat(api): weekly review analytics and career floor evaluation #77
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/issue-30-review"
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?
Motivation
Phase 4 ends with the weekly review: an honest, read-only account of what was recorded against what was planned. The obvious implementations all lie — counting allocated calendar blocks as work done, reading an unobserved day as a zero, presenting planned block length as if it were effort, folding service-confirmed facts together with externally observed differences, and dressing patterns up as diagnoses. The specification (
docs/technical/workflows.md#weekly-analytics) demands the opposite: every metric states its numerator, denominator, observation interval and coverage; an unobserved period is a gap, never a zero; allocation is not attainment; external differences are not deliberate acts; a corrected fact is folded once and stays traceable; and nothing here reschedules, queues or cancels anything.Changes
src/api/reviews.rs(new) —POST /v1/reviews(read scope: no operation key, no calendar write, no journal row). It validates{period: "week", anchor_date?}before any read, then assembles the metrics, evidence and advisory flags from the reviewed week's live reads and one folded journal read.src/domain/analytics/(new) — six focused modules:mod.rs— the one metric shape,Metric { name, numerator, denominator, unknown_count, coverage }, andMetricCoverage { from, to, view, attribution, unit, observed, unknown, detail }, so a consumer never special-cases a metric;interval.rs— the Monday–Monday local week and its seven half-open days;career_floor.rs— weekday attainment, classified by #22's ownCareerFloor::from_day_outcomes, so the review and the next-action policy cannot disagree;completions.rs— service-confirmed completions and observed external completion differences as two metrics over one denominator;duration.rs— planned block minutes and reported effort minutes kept apart, with unknown actual durations excluded and counted;deferrals.rs— items pastdeferral_review_count, raising #25's existingDeferralReviewprompt (its message, its four options) and deciding nothing.src/history/timeline.rs— new journal reads:effective_outcomes()(the corrected view, one entry per original fact, carrying the standing assertion plus the original/correction link),deferrals_in()(only the evidence classes that establish a deliberate deferral, grouped per item, with unattributable facts disclosed), andcompletions_in()(confirmed vs observed, split by evidence class).day_outcomes()is now defined over the folded read, so the career floor has exactly one definition for/v1/nextand the review.src/api/mod.rs— route registration plus the read-scope handler.src/cli.rs—life review --period week [--anchor-date YYYY-MM-DD] [--json], a read-scope POST throughpost_read_envelope, with a human renderer that prints each ratio beside its observed/unknown coverage, then the flags and the evidence.skills/life/references/commands.md—life reviewmoved into the Reads table; it is no longer advertised as unimplemented.tests/review_tests.rs, unit tests ininterval.rs/reviews.rs; the CLI/API fixtures that pinned/v1/reviewsas a 501 stub now probe/v1/sync, and the skill package's unimplemented-command count reflects the remaining two.Verification
nix develop --command cargo test— every suite green, with 16 new integration cases intests/review_tests.rscovering, per acceptance criterion:1/2withunknown_count 3; a live Friday block that was never reported changes neither the numerator nor the unknown count, and contributes only to the planned half of the duration metric.0/5, unknown 0with nohistory_incompletewarning, while a week with nothing recorded answers0/0, unknown 5with the gap named.from/to,view: corrected,attribution,unit,observed/unknownand detail lists.120mplanned against30mreported, one unknown duration counted, one block reported and one never reported; a transparent event is not a block.observed_externaldifference is not a deferral, and an unattributable deferral is disclosed rather than attributed.event_id,original_event_idandcorrected_by.review_flagciting the inputs it was asked about andjev-1.13.0/review_flag_v1, with no diagnostic language; an unreachable provider yieldsjudgment_unavailablewith byte-identical metrics and evidence.Related Issues
Closes #30
Coordinator review — APPROVED
Verified
0cdbfa7myself:cargo test736 passed / 0 failed (16 new review tests),cargo clippy --all-targets -- -D warnings0 errors,cargo fmt --checkclean.What I checked beyond the summary — this is the slice where "say what you measured" is easiest to fake, so the assertions matter:
0/5withunknown 0, the five dates listed indetail.observed_days, and no warning; a week with nothing recorded gives0/0withunknown 5, an emptyobserved_days, and ahistory_incompletewarning naming the days. That is precisely the distinctionworkflows.mddemands, and it is carried by the warning as well as the counts.focus_block_effort'splanned_minutes, never in the career-floor numerator, and the non-qualifying Tuesday lands inunmet_dayswhile unobserved days land inunknown_days— so each day is classified once, explicitly. Reusing#22'sCareerFloor::from_day_outcomeskeeps one definition of the floor in the codebase.observed_externalreturn toNEEDS-ACTIONcorrectly excluded — so an external difference is reported as an observation rather than promoted to a service fact.unreported_blocks 1), which is the disclosure the doc asks for.VIEW_CORRECTED), deferrals count only deliberate recorded ones and reuse #25's own review prompt and its four options rather than inventing a second one, and the advisory flag isreview_flag.v1's interpretation with ajudgment_unavailablepath that leaves every deterministic metric unchanged.life reviewwas unimplemented were moved to a still-unimplemented verb (sync) inapi_tests.rs,cli_tests.rsandskill_package_tests.rs, and the skill's command reference movedreviewto Reads — the coordinated-update habit this codebase has kept throughout.Merging. This closes the last issue of the original 36.
feat(api): weekly review analytics and career floor evaluation (#30)to feat(api): weekly review analytics and career floor evaluation