--- name: report description: Summarise work logs into a yearly, monthly, weekly or daily report. Resolve the period with tools/report-range.sh, resolve the template with tools/report-template.sh - a project's .jsc/templates/report-{period}.md wins over the skill's own copy - then read every log page listed in LOG_CONTENTS and keep the entries dated inside the range. Fill the template with real aggregates (entry count, repositories, elapsed time, token usage, blockers, carry-overs) and write it to wiki REPORT_{HASH}, hashed from {owner}/{repo}/{period}, appending the period as a new section. Use when someone asks for a work summary over a period; not for recording a single work package, which is jsc-log:worklog. --- # report — summarise work logs by period Reading and aggregating the log pages **MUST run as a sub agent**: it reads every page in `LOG_CONTENTS` and only a handful of entries survive the date filter. Report content is written in Traditional Chinese (STE100). ## 1. Period Ask for the period per the `jsc-ask:ask` rules when the caller did not name one: `daily`, `weekly`, `monthly`, `yearly`. Each option states what it covers. Run `tools/report-range.sh {period} [yyyy-MM-dd]`. It prints `{start}{end}{label}{period}`, both dates inclusive. The base date defaults to today; pass one to re-run an earlier period. | Exit | Meaning | Do | | --- | --- | --- | | 0 | Range printed | Read start, end and label out of the four fields | | 2 | Period name or base date rejected | Ask per the `jsc-ask:ask` rules which of the four periods was meant, or fix the `yyyy-MM-dd` base date, then rerun | | 4 | This machine's `date` does no date arithmetic | Stop and report that the range cannot be computed here. Never work the dates out by hand: week boundaries and month lengths are exactly where a hand-rolled range quietly loses a day | Done when start, end and label are known. ## 2. Resolve and collect Run these four lines of work in parallel — none of them consumes another's output, and the log pages are the slow one: 1. **Template.** `tools/report-template.sh resolve {period}` from the working directory prints `{path}{project|skill}`. 2. **Log pages.** `jsc-gitea/tools/gitea.sh wiki-repo LOG`, then read `LOG_CONTENTS` through `jsc-gitea:wiki`, then read **every** log page it lists, one sub agent per page. 3. **Lessons (yearly only).** `gitea.sh wiki-repo LEARN`, then read `LEARN_CONTENTS` through `jsc-gitea:wiki` for the 全年教訓 section. Resolve `JSC_WIKI_REPO_LEARN` on its own: the LOG repo resolved in line 2 never stands in for it, and LOG and LEARN pages routinely live in different wiki repos. Other periods skip this line. 4. **Report repo.** `gitea.sh wiki-repo REPORT`, so step 3 has its target ready. Exit branches for the external calls above: | Call | Exit | Do | | --- | --- | --- | | `report-template.sh resolve` | 0 | Use the path; name the `project` or `skill` source in the final report. `project` means the working directory holds `.jsc/templates/report-{period}.md` and that file wins — the same period rendered from two templates has to be traceable to the file that shaped it | | `report-template.sh resolve` | 2 | Period name or start directory rejected. Rerun from the working directory with the period from step 1 | | `report-template.sh resolve` | 3 | Neither the project copy nor the skill's own copy exists. Stop and report that `templates/report-{period}.md` is missing from the plugin; do not invent a layout | | `gitea.sh wiki-repo LOG` | 3 | Stop and report that no wiki repo is configured for LOG, naming `JSC_WIKI_REPO_LOG` and `JSC_WIKI_REPO`. Ask per the `jsc-ask:ask` rules, then rerun. Without log pages there is nothing to summarise | | `gitea.sh wiki-repo LEARN` | 3 | Fill the 全年教訓 section with 無 and say the LEARN wiki repo is unset. The rest of the yearly report still stands | | `gitea.sh wiki-repo REPORT` | 3 | Carry on collecting; step 3 handles the skipped write | | `gitea.sh wiki-repo` any type | 2 | The page type was misspelled. Fix the argument and rerun | | `jsc-gitea:wiki` read | 4 | The page is genuinely absent. **Only this code** lets `LOG_CONTENTS` or a listed log page count as zero entries; name it in the close-out | | `jsc-gitea:wiki` read | 7 | The token is invalid or lacks permission. Stop and report the token problem. Counting this as zero entries publishes a report that says a period held no work when the work is sitting on a page nobody managed to read | | `jsc-gitea:wiki` read | 8 | Some other API failure. Stop and report that status; a page that failed to load must never be counted as an empty page | Then aggregate. Save the collected page contents to files and run: `tools/log-aggregate.sh {start} {end} {page file} ...` It prints `ENTRIES=`, `REPOS=`, one `REPO=` line per repository, `ELAPSED_MINUTES=`, `ELAPSED_ENTRIES=`, `ELAPSED_MISSING=`, one `TOKEN=` line per CLI, `TOKEN_MISSING=` and one `STATUS=` line per status. It enforces the no-estimate rule in code: an entry with no 花費時間 stays out of the total and lands in `ELAPSED_MISSING`, and a range where nothing carried a time prints `ELAPSED_MINUTES=無資料` rather than `0`. | Exit | Meaning | Do | | --- | --- | --- | | 0 | Aggregates printed | Carry the printed values into the template unchanged. Never recompute or round them by hand | | 2 | Dates rejected, or start later than end | Rerun with the step 1 values | | 3 | Zero entries inside the range; the zero-filled aggregate is still printed | Produce the report anyway, with counts of 0 and a line naming the empty range. A silent "no report" cannot be told apart from a failure | | 4 | A page file is unreadable | Stop and report which file, rather than reporting a smaller total | Blockers and unfinished work packages come from the 任務狀態 and 遇到的困難與解決方式 parts of the surviving entries; the sub agent lists them verbatim. Done when the template path, its source, the aggregate lines and the blocker list are all in hand. ## 3. Write Follow the template's headings and tables exactly, including ones with no data: an empty section stated as 無 is information, a silently dropped section is not. Write through `jsc-gitea:wiki`: - Repo: the REPORT repo from step 2, line 4. - Page: `REPORT_` plus `gitea.sh hash-id "{owner}/{repo}/{period}"`, where `{owner}/{repo}` is the REPORT wiki repo. Year, month, week and day each get their own page. - Read the page first and branch on the exit code the underlying `gitea.sh wiki-get` returned. **Only exit 4 means the page is not there yet** and may be built from scratch. On exit 0 the existing sections are in hand, so append into them. On exit 7 the token is invalid or lacks permission, and on exit 8 the API failed some other way: both leave the earlier periods unknown, so stop, report the status and write nothing — a page rebuilt on top of an unread read loses every period already on it. - Append this period as a new section, newest first. Rerunning the same period replaces that period's section only, leaving the other periods untouched. - Refresh the page's row in `REPORT_CONTENTS` from `templates/report-contents.md`: add the row if missing, otherwise refresh its 最新一期、期數 and 最後更新. Its read branches the same way — only exit 4 creates the directory page from the template, while 7 and 8 stop the run. Touch no row that belongs to another report page. | Call | Exit | Do | | --- | --- | --- | | `gitea.sh wiki-repo REPORT` | 3 | Print the finished report and say the write was skipped because no wiki repo is configured for REPORT. The report itself is still the deliverable | | `gitea.sh hash-id` | 1 | No SHA-1 helper on this machine. Stop and report that `sha1sum` or `shasum` has to be installed. Never hand-compute the hash | | `jsc-gitea:wiki` write | failure | Retry once. Still failing, stop and report the page name that was not written, and print the report body so the work is not lost. Never report a page as written when it was not | Write the content page before its row in `REPORT_CONTENTS`, never the two at once: a directory row pointing at a page whose write failed is worse than a missing row. Done when the page URL is reported, or the skipped write is reported with its reason, or the run stopped on a read that returned 7 or 8 and that status was reported. ## 4. Close State the period label, entry count, repositories covered, template source, and the page URL. Name every unfinished work package that carried over — that list is what the next period starts from. State `ELAPSED_MISSING` and `TOKEN_MISSING` whenever either is above 0, so a small total is read as missing data rather than a light week. Done when those five facts, the carry-over list and the two missing-data counts are stated.