refactor: hourlog prints a day-by-project table

One row per day, one column per project, hours in the cell. The per-day
blocks repeated the project name on every line and buried the totals.

Share, active minutes, hour ranges, and the outside-working-hours flags
move to --json, which is where the skill reads them anyway.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
naps62
2026-08-14 18:38:45 +00:00
parent 95e98a1e77
commit cd63a4c18e
2 changed files with 59 additions and 43 deletions
+26 -22
View File
@@ -43,20 +43,25 @@ missing step if not.
python3 <skill-dir>/scripts/scan-activity.py --week last
```
Reports one line per project per day: suggested hours, share of the day, active
minutes, and the hour range they fell in. The unit is a 5-minute slot in which
at least one message was written, deduplicated per project — so a 40-subagent
swarm on one project counts once, and two projects worked in parallel each keep
their own slots. Message counts would let one overnight autonomous run outweigh
a real morning.
Prints a table: one row per day, one column per project, hours in each cell.
That table is the deliverable — show it as-is rather than restating it.
Two things in the output need judgement, not arithmetic:
The unit behind it is a 5-minute slot in which at least one message was
written, deduplicated per project — so a 40-subagent swarm on one project
counts once, and two projects worked in parallel each keep their own slots.
Message counts would let one overnight autonomous run outweigh a real morning.
- **`outside working hours` lines.** Activity at 02:00 is usually an unattended
run, not work. Discount it unless the user says otherwise.
- **`unmapped:` lines.** A path with no rule. Either it is a new client
directory the config is missing — say so and ask — or it is personal work
that belongs in `exclude`. Never guess it into a client project.
Add `--json` for the evidence behind each cell: active minutes, share, hour
range, and which hours fell outside working hours. Read it before proposing
anything, and note two things there:
- **Hours flagged `outside_workday`.** Activity at 02:00 is usually an
unattended run, not work. If most of a project's minutes came from 21h-02h,
its share is inflated — say so and shift the split.
- **`unmapped` entries.** A path with no rule, excluded from the split, so the
affected days are wrong rather than merely incomplete. Either it is a new
client directory the config is missing — say so and ask — or it is personal
work that belongs in `exclude`. Never guess it into a client project.
## 2. Propose the hours
@@ -71,13 +76,8 @@ job is the judgement it cannot do:
- One project at 85% or more: round it up to the whole day rather than leaving
a token 1h on the other.
- Discount hours flagged `outside`. If most of a project's minutes came from
21h-02h, its share is inflated by an unattended run — say so and shift the
split rather than passing the number through.
- Days marked `under 30min, treat as empty` get nothing proposed.
- An `unmapped:` line with real minutes means the split is wrong, not just
incomplete: those minutes were excluded from the division. Resolve the
mapping before proposing hours for that day.
- Days marked `*` in the table get nothing proposed.
- Correct the split for the two things flagged in step 1 before proposing it.
Never scale a day *down* because its transcripts are thin. A quiet day is a
normal working day unless the user says it was not, or the timesheet already
@@ -100,9 +100,13 @@ planned hours) or absent. That splits the proposal in two:
## 4. Show the table, then ask
One row per project per day: date, weekday, project, proposed hours, what the
timesheet currently says, and the action (confirm / adjust / add / skip).
Flag every row where the evidence was weak or outside working hours.
The scan's table, one row per day and one column per project, with the
timesheet's current hours beside each proposed cell where the two differ. Mark
any day that needs a new entry rather than a confirmation.
Keep it to that table plus a line for anything you had to judge — a discounted
overnight run, an unmapped path, a day you left empty. No commentary on days
that were straightforward.
Then ask once, plainly, whether to submit. Wait for an answer. Silence, a
timeout, or "user may be away" is not approval — leave the timesheet alone and