odoo-timesheets/.claude/skills/monthly-review/SKILL.md
Jef Roosens 2cd4812bed
Add monthly-review skill
Add .claude/skills/monthly-review: a Claude Code skill that builds a
higher-level monthly timesheet review by synthesizing the weekly review
sections of the month's week notes, and writes it as a note in
Work / Self-Reviews.

Uses a strict calendar-month day filter (straddling weeks count only for
their in-month days), the weekly review sections as the source of truth,
and the CLI only for per-week totals. The review has a month-level
narrative (shape, major threads, recurring work) plus an inspections
section: time allocation, stuck/recurring threads, and long weeks (a
low-logged week is treated as unlogged leave, not reduced output).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 09:31:19 +02:00

14 KiB

name description
monthly-review Generate a higher-level monthly timesheet review from the weekly review sections of one calendar month's Joplin week notes, and write it as a note in Work / Self-Reviews. Produces a month-level narrative of the work done plus an inspections section (time allocation, stuck/recurring threads, long weeks). Use when the user asks for a monthly review, a month recap, to "review my month", to summarize a month of work, or to prep for a monthly/checkin overview. Optionally takes a month (e.g. "April", "2026-04", "last month") to target a month other than the current one.

Monthly timesheet review

Build a month-level review by synthesizing the weekly review sections that already exist in that month's week notes, and write it into a note in Work / Self-Reviews. The weekly reviews are granular (one week each); this zooms out: collapse the week-by-week detail into month-level arcs, say where the big threads landed, and surface patterns that are only visible across the whole month.

This is the bigger sibling of the weekly-review skill. The reference for the target output is the existing 2026 - Year Review (W01-W22) note in Work / Self-Reviews: it is synthesized from weekly review sections at year scale. A monthly review is the same idea, one month wide, plus an explicit inspections section.

Read README.md and CLAUDE.md first if you are not already familiar with the project. The timesheet structure, table format, and Joplin notebook layout are described there. The weekly-review skill describes the weekly review format this one consumes.

Inputs

  • Optional target month. Accept a month name (April), YYYY-MM (2026-04), last month, this month, or any date (the month containing it). Default to the current calendar month relative to today.
  • If today is in the first days of a month and the request is ambiguous, the user most likely means the month that just ended. Confirm which month before doing the work.
  • A review run for an incomplete (current, still-running) month is fine, but say in the note that it is partial.
  • The CLI reads timesheets from Joplin with --joplin. Config (token, project map) is already set up; do not ask for it.

What a month is here

A calendar month, strict day filter: only days that actually fall in the month count. ISO weeks do not align with months, so a week that straddles the boundary (e.g. the week of Apr 27 with days in both April and May) is included only for its in-month days. The out-of-month days of a straddling week belong to the other month's review.

Consequence: a straddling week whose in-month days have no logged entries (e.g. for May, the week of Apr 27 only reaches into May 1-3, a Friday-to-Sunday with a public holiday and no entries) contributes nothing and drops out entirely. Do not pull its review in.

Steps

1. Resolve the month and find its week notes

  • Resolve the target month to its first and last calendar day, relative to today. Convert any relative expression to an absolute month (e.g. with today 2026-05-30, "last month" = April 2026, "this month" = May 2026).

  • Week notes live in Work / Timesheets / <year>, titled YYYY - WNN. List them:

    find_notes_in_notebook("Work/Timesheets/<year>")
    

    A month near a year boundary (January, December) can pull weeks from two year notebooks; list both when relevant.

  • For each candidate week note, read its first heading # Week of <Monday> - Review to get the week's Monday. The week spans Monday..Monday+6. Include the week if that span intersects the target month (week-Monday <= month-last-day AND week-Sunday >= month-first-day).

  • For a straddling week (Monday before the 1st, or Sunday after the last day), only the in-month days count (see "What a month is here"). Check whether those in-month days actually have logged entries:

    • If they do, include the week but treat only the in-month days as this month's work. Read the day tables for those days to see what was worked, and use the weekly Summary for context; do not attribute the out-of-month days' work to this month.
    • If the in-month days have no entries, drop the week entirely.
  • Record the list of weeks that contribute days to this month (e.g. W19-W22) for the title and caveats.

2. Read the weekly review sections (primary source)

For each included week note, read the review block: everything from the # Week of YYYY-MM-DD - Review heading down to (not including) the first day heading (# <weekday> - ...). Use get_note(note_id, force_full=true) and take that top block. It holds the three subsections the weekly skill writes:

  • ## Summary — the narrative of own work, grouped by theme, with rough per-theme times and a meetings line. This is the spine of the month narrative.
  • ## Reviews — work that was only reviewing other people's MRs, with a rough total. Sum these across the month for the review-load figure.
  • ## Loose ends — open checklist items, recurring unclosed stories, carry-over. This is the spine of the stuck/recurring-threads inspection.

The weekly reviews already carry the substance and the user's voice. Draw the narrative from them; do not re-derive everything from the raw day tables. The weekly review section is the source of truth for what the week was about.

Carry over the Joplin note links ([label](:/<id>)) from the weekly sections when you reference the same ticket; do not invent new ids.

3. Get per-week totals (cross-check, long-week detection)

Run, once per included week, using that week's Monday date:

uv run timesheets summary -w -ss --joplin <monday-date>   # per-day + week total

Use this to compute the month total and to spot long weeks. The -ss output gives a per-day breakdown, so for a straddling week sum only the in-month days rather than the whole-week total. Cross-check against the total stated in the week's ## Summary. The CLI total is occasionally garbage from data-entry typos in the raw tables (a week can show a nonsense 100h+). When the CLI total and the week note's stated total diverge wildly, trust the week note and flag the week in Caveats. Never sum hours by hand from the raw tables.

4. Write the month narrative

Higher altitude than a weekly review. The reader should come away knowing what the month was about and where the big threads landed, not the day-to-day.

  • Lead with the shape of the month: one short paragraph. What were the one or two centers of gravity? Was it focused on a flagship effort, or fragmented across many small things? Did a release, a customer, or an interruption dominate a stretch?
  • Group own work by major project/theme, most time first. For each, give a few plain sentences: what it was, how it progressed across the month's weeks, and where it ended the month (landed / merged / still in flight / handed off). Merge a theme that appears in several weekly summaries into one month-level thread rather than repeating it per week.
  • Recurring / continuous work in a tighter list: bug-fixing load, the areas that came up repeatedly (specific subsystems), customer/incoming work, MCP/AI, security/ISMS, etc. Mirror the "Recurring areas" / "Continuous work" split in the year-review note when there is enough material.
  • Meetings: name the noteworthy ones (brainstorms, retros, growth-path, customer/technical meetings, trade fairs). Fold dailies and Factry Flow into a one-line catch-all. Pull these from the weekly summaries' meetings lines.
  • Reference tickets by paraphrase + id in brackets, same convention as the weekly skill, and only link ids that a weekly section already linked. At month scale, reference fewer tickets than a weekly review would; lead with threads, not ticket numbers.

5. Write the inspections section

This is the point of the monthly view: patterns visible only across the whole month. Cover these three lenses (and only these unless the user asks for more):

  1. Time allocation.

    • Own work vs reviewing other people's MRs: sum the weekly ## Reviews totals and express the review load as a rough share of the month. A heavy review month is worth calling out (it is real, valuable work, but it is a large time sink and the user tracks it separately from own work).
    • The split across major projects/themes for the month.
    • How fragmented the month was: many small bugs and heavy context-switching vs sustained focus on one or two threads. The weekly summaries say this directly ("fragmented week", "no single theme", "one theme dominated"); aggregate that judgement.
  2. Stuck / recurring threads.

    • Tickets and loose ends that appear in multiple weeks' ## Loose ends or recurring-story lists and never closed within the month.
    • Repeated rework: rebases of the same big branch, repeated rounds of fixing the same failing tests or de-flaking the same suite (e.g. Cypress).
    • Threads that opened early in the month and were still open at month end.
    • These are candidates the user may want to push to close or escalate.
  3. Long weeks (only).

    • Flag weeks that clearly ran over 40h and say what drove them (evening trade fairs, late stress-test or customer work, a release crunch).
    • Do not flag short or low-hour weeks as reduced output or a concern. The user always works full weeks. A week that logs under 40h almost always means vacation or time off that was simply not entered in the timesheet, not less work done. At most mention a low-logged week once, in Caveats, as a data-entry gap, never in the workload inspection as a productivity signal.

Keep inspections concrete and tied to the data. If a lens has nothing real for this month, say so in a line rather than padding.

6. Voice

Write it the way the user writes, not the way an assistant writes. The reference is the user's Express Guide OpenTelemetry note (in Knowledge / OpenTelemetry): read it before drafting and match its register.

How the user actually writes:

  • Plain and matter-of-fact. States what a thing is and what happened, e.g. "ArgoCD is gitops CD for Kubernetes, it reconciles the live cluster against the git repo". Defines with "X is Y", gives concrete examples in parentheses with "e.g.". No drama.
  • Full sentences, normal capitalization, English. No Dutch, no lowercase-everything, no gwn/da/ge (that is only how the rough free-text is drafted, not how finished notes read).
  • Light first person where natural ("I changed the GC to be less aggressive", "I'm explaining them here").
  • Bold for the key term that starts a thread or definition, the way the Express Guide bolds Counter, resource, etc.
  • -> for results/consequences is fine. No em dashes; use commas, parentheses, colons, ->, or new sentences.

Avoid the AI tells the user does not use:

  • No journalistic punch verbs or set-piece phrasing: not "blew up", "the spine of the month", "rides with it", "pivoted hard", "exploded".
  • No editorializing flourishes: not "worth keeping visible", "risks drifting", "bit-rot risk". State the fact and, if needed, the plain consequence.
  • No balanced "not X, but Y" rhythm or rule-of-three lists for effect.
  • Keep the altitude high (what the thread was and where it landed), but the prose flat and concrete. Exact config values and internal symbol names stay out (the story logs hold those); centre of gravity is the user's own phrase and is fine.

7. Confirm, then write the note

  • Show the full draft to the user first and ask for confirmation. This is LLM-generated prose going into a durable note; do not write blindly. Apply any edits the user asks for.
  • Write it as a note in the Work / Self-Reviews notebook. Title convention, mirroring the year-review note: YYYY - <Month> Review (Wxx-Wyy), e.g. 2026 - May Review (W18-W22).
  • Before creating, search for an existing note for this month (find_notes_in_notebook("Work/Self-Reviews")). If one exists, update it with edit_note rather than creating a duplicate. The Joplin tools cannot delete notes, so a wrongly-created duplicate can only be blanked, not removed; check first. Only create a new note with create_note when none exists.
  • After writing, re-fetch the note (or report the diff) so the user can verify.

Output structure

# <Month> <Year> Review (Wxx-Wyy)

Synthesized from the weekly review sections of the Wxx-Wyy timesheet notes.

## Shape of the month

<one short paragraph: the one or two centers of gravity, overall character>

## Major threads

<own work grouped by project/theme, most time first; where each landed>

## Recurring & continuous work

<bug-fixing load, repeated subsystems, customer/incoming work, meetings line>

## Inspections

**Time allocation**<own vs review share, project split, fragmentation>
**Stuck / recurring threads**<multi-week carry-overs, repeated rework, still-open>
**Long weeks**<weeks over 40h and what drove them; none -> say so>

## Caveats

<missing week notes, unreliable CLI totals, low-logged weeks as data gaps>

Adapt the headings to the material; this is a shape, not a rigid template. Match the depth of the year-review note: enough to be useful, not a per-ticket ledger.

Edge cases

  • Missing or empty week note. If an included week has no review section (e.g. it was never reviewed, or is a near-empty stub), note it in Caveats and work from what is there. Do not fabricate a week's content. If most of the month's weeks lack review sections, tell the user the monthly review will be thin and suggest running the weekly reviews first.
  • Straddling weeks count only for their in-month days (see "What a month is here"). If the in-month days have no entries, drop the week. Use the per-day CLI breakdown to attribute hours.
  • Unreliable CLI totals. Prefer the week note's stated total over a wildly divergent CLI total; flag it in Caveats.
  • Low-logged weeks are not short weeks. See step 5, lens 3: treat them as unlogged-vacation data gaps, never as reduced output.
  • Never touch the week notes or the checkin notes. This skill only reads the weekly review sections and writes a new note in Work / Self-Reviews. Checkin notes in Work / Meetings / Checkins are the user's own and are off-limits.
  • Do not modify the day tables in any week note.