diff --git a/skills/hourlog/SKILL.md b/skills/hourlog/SKILL.md index 5b5ff4d..e1b0f22 100644 --- a/skills/hourlog/SKILL.md +++ b/skills/hourlog/SKILL.md @@ -43,13 +43,9 @@ missing step if not. python3 /scripts/scan-activity.py --week last ``` -Prints a drawn grid: one row per day, one column per project holding +Prints a markdown table: one row per day, one column per project holding `hours · share · active minutes`, then a totals row. That table is the -deliverable — show it as-is, inside a fenced code block so the terminal -renderer leaves the borders alone, rather than restating it in prose. - -`--markdown` swaps the grid for pipes when the destination renders tables -itself (a PR body, an issue, a doc). +deliverable — paste it as-is rather than restating it in prose. 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 diff --git a/skills/hourlog/scripts/scan-activity.py b/skills/hourlog/scripts/scan-activity.py index 1c96b34..0925a0f 100755 --- a/skills/hourlog/scripts/scan-activity.py +++ b/skills/hourlog/scripts/scan-activity.py @@ -14,16 +14,11 @@ transcripts on one project counts once, and two projects worked in parallel each keep their own slots. Message counts would make one overnight autonomous run outweigh a real morning; wall-clock presence does not. -Output is a table: one row per day, one column per project, each cell holding -suggested hours, share of the day, and the active minutes behind it. The -suggestion splits a nominal working day by share, in 15-minute steps — active -minutes are a floor on real work, never a measure of it, so the day's length -comes from the calendar and only the split between projects comes from the -sessions. See SKILL.md. - -Default rendering is a drawn grid, because a markdown table has no borders of -its own and terminal renderers vary in whether they draw any. --markdown emits -pipes instead, for pasting somewhere that does render them. +Output is one line per project per day: suggested hours, share of the day, and +the active minutes behind it. The suggestion splits a nominal working day by +share, in 15-minute steps — active minutes are a floor on real work, never a +measure of it, so the day's length comes from the calendar and only the split +between projects comes from the sessions. See SKILL.md. """ import argparse import collections @@ -160,35 +155,17 @@ def fmt_hour_list(hours): return ", ".join(out) -def widths(rows): - return [max(len(r[i]) for r in rows) for i in range(len(rows[0]))] - - -def _cells(row, w, align_right): - return "| " + " | ".join( - c.rjust(w[i]) if i in align_right else c.ljust(w[i]) - for i, c in enumerate(row)) + " |" - - -def box_table(rows, align_right=()): - """Render rows (first is the header) as a grid with every cell bordered.""" - w = widths(rows) - rule = "+" + "+".join("-" * (n + 2) for n in w) + "+" - out = [rule] - for row in rows: - out += [_cells(row, w, align_right), rule] - return "\n".join(out) - - def md_table(rows, align_right=()): """Render rows (first is the header) as a padded markdown table.""" - w = widths(rows) + w = [max(len(r[i]) for r in rows) for i in range(len(rows[0]))] + def line(cells): + return "| " + " | ".join( + c.rjust(w[i]) if i in align_right else c.ljust(w[i]) + for i, c in enumerate(cells)) + " |" sep = "|" + "|".join( ("-" * (w[i] + 1) + ":") if i in align_right else ("-" * (w[i] + 2)) for i in range(len(w))) + "|" - return "\n".join( - [_cells(rows[0], w, align_right), sep] + - [_cells(r, w, align_right) for r in rows[1:]]) + return "\n".join([line(rows[0]), sep] + [line(r) for r in rows[1:]]) def main(): @@ -198,8 +175,6 @@ def main(): ap.add_argument("--week", choices=["last", "this"]) ap.add_argument("--config", default=CONFIG) ap.add_argument("--json", action="store_true") - ap.add_argument("--markdown", action="store_true", - help="pipe table for pasting, instead of a drawn grid") a = ap.parse_args() cfg = load_config(a.config) @@ -333,13 +308,11 @@ def main(): rows.append([f"{e['date']} {e['weekday']}"] + cells + [fmt_hours(day_sum) if day_sum else "—", "; ".join(flags)]) - bold = (lambda s: f"**{s}**") if a.markdown else (lambda s: s) - rows.append([bold("total")] + - [bold(fmt_hours(week[c])) for c in cols] + - [bold(fmt_hours(sum(week.values()))), ""]) + rows.append(["**total**"] + + [f"**{fmt_hours(week[c])}**" for c in cols] + + [f"**{fmt_hours(sum(week.values()))}**", ""]) right = set(range(1, len(cols) + 2)) - render = md_table if a.markdown else box_table - print(render(rows, align_right=right)) + print(md_table(rows, align_right=right)) if unmapped: print("\nunmapped paths — add them to the config or the exclude list:")