fix(overwrite): 只有頁面真的不存在才建新頁
- What:worklog、learn、report 三支技能共六處讀取分流改寫,只有結束碼 4 才建新頁; 結束碼 7 與 8 一律中止,一個字都不寫。三份目錄頁樣板補上寫入語意,明寫禁止整頁覆蓋、 不得改動別人的列。usage-stats.sh 的參數護欄改成明確回傳結束碼 2。 - Why:原本把「讀失敗」與「頁面不存在」當成同一件事。金鑰失效時讀取回 7,技能卻讀成 「這頁還沒有」,於是照樣板建一份新頁蓋回去。整份工作日誌會被這一筆條目取代, 既有教訓會被清成空表,報表則產出一份說「這段期間沒有工作」的假數字。 這些內容只活在 wiki 上,蓋掉就救不回來,所以這是本輪最要緊的一項。 - How:每一處讀取都先看結束碼再決定動作,並在技能文件裡列成表格: 0 接在既有內容後面附加,4 才從樣板建頁,5 缺網址就中止,7 金鑰或權限問題就中止, 8 其他 API 失敗就中止。目錄頁一律先讀整頁再改那一列。 stats 也補上分流,參數錯誤不再被讀成「零次」。 - Who:worklog、learn、report、stats 四支技能的 wiki 讀寫與統計輸出。
This commit is contained in:
+41
-12
@@ -21,13 +21,15 @@ Guardrail: append entries at the end of the page and leave the existing ones unt
|
||||
|
||||
## Items to collect
|
||||
|
||||
Rows 3, 4, 5 and 6 each hit a different source and none of them reads another's output, so **fetch the four in parallel**. Rows 1 and 2 are two local `git` reads that join the same batch.
|
||||
|
||||
| # | Item | Source |
|
||||
| --- | --- | --- |
|
||||
| 1 | Repository name | Parse `{owner}/{repo}` from `git remote get-url origin`. This is the code repo — never pass it to `wiki-url`, which takes the wiki-hosting repo |
|
||||
| 2 | Branch name | `git branch --show-current` |
|
||||
| 3 | Plan name | Absolute link to the plan page: `[PLAN_{HASH}](<url>)`. Resolve the hosting repo with `jsc-gitea/tools/gitea.sh wiki-repo PLAN`, then take `<url>` from `gitea.sh wiki-url <that repo> PLAN_{HASH}` — PLAN and LOG may live in different wiki repos, and `[[...]]` only resolves inside one wiki. `wiki-repo` exit 3 (no wiki repo configured for that type) or `wiki-url` exit 4 (page not found) → fill the literal 「無」 for this row and carry on; a `worklog` run triggered from `maintain` normally has no plan page |
|
||||
| 4 | Work package id | Absolute link to the work package heading: `[WP-xx](<url>#wp-xx)`. Resolve the hosting repo with `gitea.sh wiki-repo ANALYZE`, then take `<url>` from `gitea.sh wiki-url <that repo> ANALYZE_{HASH}`. A comment-fix round links to the same work package it belongs to. Same fallback as row 3: `wiki-repo` exit 3 or `wiki-url` exit 4 → fill 「無」 and carry on |
|
||||
| 5 | Elapsed time | `jsc-hooks/hooks/session-timer.sh report {session_id}` (seconds; convert to h/m). Count only this task, so read it at the moment the task ends |
|
||||
| 3 | Plan name | Absolute link to the plan page: `[PLAN_{HASH}](<url>)`. Resolve the hosting repo with `jsc-gitea/tools/gitea.sh wiki-repo PLAN`, then take `<url>` from `gitea.sh wiki-url <that repo> PLAN_{HASH}` — PLAN and LOG may live in different wiki repos, and `[[...]]` only resolves inside one wiki. `wiki-repo` exit 3 (no wiki repo configured for that type) or `wiki-url` exit 4 (page not found) → fill the literal 「無」 for this row and carry on; a `worklog` run triggered from `maintain` normally has no plan page. `wiki-url` exit 5 → stop and report that the page carries no `html_url`; never assemble the URL by hand. `wiki-url` exit 7 (token invalid or no permission, HTTP 401/403) or exit 8 (other API failure) → stop and report the token or API status; never fill 「無」, because that records a page that exists as a page that does not |
|
||||
| 4 | Work package id | Absolute link to the work package heading: `[WP-xx](<url>#wp-xx)`. Resolve the hosting repo with `gitea.sh wiki-repo ANALYZE`, then take `<url>` from `gitea.sh wiki-url <that repo> ANALYZE_{HASH}`. A comment-fix round links to the same work package it belongs to. Same branching as row 3: `wiki-repo` exit 3 or `wiki-url` exit 4 → fill 「無」 and carry on; `wiki-url` exit 5 → stop and report that the page carries no `html_url`, never assemble the URL by hand; `wiki-url` exit 7 or 8 → stop and report the token or API status, never fill 「無」 |
|
||||
| 5 | Elapsed time | `jsc-hooks/hooks/session-timer.sh report {session_id}` prints `{sid} {seconds}` and always exits 0. Convert the seconds to h/m and read it at the moment the task ends, so it counts only this task. `0` means the timer holds no start record for that session, not a task that took no time: fill the literal 「無資料」 and say the timer had no record. Never estimate the duration from the transcript |
|
||||
| 6 | Token usage | `tools/token-usage.sh <cli> {session_id}` per CLI that ran; it prints `input<TAB>output`. Pass the same `{session_id}` as row 5 so the elapsed time and the token count describe one task. Fill `N/A` in both columns when it prints `N/A`; exit 2 means the CLI name is not one of claude / codex / copilot / antigravity / kiro, so fix the name and rerun |
|
||||
| 7 | Task status | One of the literal values 「完成」, 「部分完成」, 「阻塞」 (with reason when blocked). Derive it from the session when the session shows it; otherwise ask via `jsc-ask:ask`, offering those three literals as the options and stating each option's impact scope (「完成」 closes the task, 「部分完成」 leaves the remainder open for the next run, 「阻塞」 records the blocker and hands it back to the operator) |
|
||||
| 8 | Details and outputs | One line per changed file or produced page: what changed there and why. A round that changed nothing says what was tried and why it was dropped |
|
||||
@@ -38,12 +40,39 @@ The `{HASH}` in every page name above is computed with `jsc-gitea/tools/hash-id`
|
||||
|
||||
## Write the entry
|
||||
|
||||
1. Resolve the wiki repo hosting LOG pages with `gitea.sh wiki-repo LOG`: it reads `JSC_WIKI_REPO_LOG` first and falls back to `JSC_WIKI_REPO` only when that one is unset. Inspect the inherited shell environment first, and ask the user per the `jsc-ask:ask` rules when neither resolves. Keep to the LOG variable — another page type's `JSC_WIKI_REPO_{TYPE}` never stands in for it. Done when the hosting `{owner}/{repo}` is known.
|
||||
2. Compute `{HASH}` from the code repo's `{owner}/{repo}` with `jsc-gitea/tools/hash-id`. Done when the 8-character `{HASH}` is known.
|
||||
3. Run `tools/worklog-target.sh "{HASH}" all`. Use `PAGE` for `LOG_{HASH}` and `CONTENTS` for `LOG_CONTENTS`. Done when both page names are known.
|
||||
4. Fix the work week: the Friday of the current work week drives the page content and the row dates. Done when that Friday is fixed as a `yyyy-MM-dd` date.
|
||||
5. Fill `templates/log-entry.md` with the ten facts of this one task and save it to a file. Done when that file holds exactly one entry.
|
||||
6. Run `tools/worklog-pending.sh merge {HASH} {entry file}`. It prints `MERGED=` (pending content in time order, then this task's entry), `CLAIM=` (the pending files it took) and `PENDING=` (how many). Pending content was written by an earlier stage that ended without a work log, so it belongs in **this** write. Done when `MERGED` and `CLAIM` are known.
|
||||
7. Read `PAGE` via `jsc-gitea:wiki`. Create it from the structure in `templates/log-entry.md` when it does not exist, then append the whole `MERGED` content at the end. Done when every entry in `MERGED` exists on `PAGE`.
|
||||
8. Update `CONTENTS` in the same pass (apply `templates/log-contents.md`; add the row if missing, otherwise refresh its 條目數 and 最後更新). Done when the row for `PAGE` carries this week's Friday date.
|
||||
9. Close the pending area on the result of steps 7 and 8: `tools/worklog-pending.sh commit {HASH} {CLAIM}` after both succeeded, or `tools/worklog-pending.sh abort {HASH} {CLAIM}` after either failed. `abort` keeps every pending file for the retry, so keep the entry file too and rerun from step 6. Done when one of the two ran and printed its count.
|
||||
1. Resolve the LOG wiki repo and the entry's `{HASH}` **in parallel** — neither needs the other.
|
||||
- Repo: `gitea.sh wiki-repo LOG`. Exit 3 means no LOG wiki repo is configured; hand that to `jsc-gitea:wiki`, which owns the resolution order and the question to ask. Exit 2 means the type argument was misspelled, so fix it and rerun.
|
||||
- Hash: `jsc-gitea/tools/hash-id "{owner}/{repo}"` on the code repo from row 1. Exit 1 means this machine has no SHA-1 helper: stop and report that `sha1sum` or `shasum` has to be installed, and never hand-compute the hash.
|
||||
|
||||
Done when the hosting `{owner}/{repo}` and the 8-character `{HASH}` are both known.
|
||||
2. Run `tools/worklog-target.sh "{HASH}" all` and `tools/worklog-target.sh friday` in parallel. `all` prints `PAGE=LOG_{HASH}` and `CONTENTS=LOG_CONTENTS`; `friday` prints the Friday of the current work week as `yyyy-MM-dd`, which drives the page content and the row dates. Exit 2 means the arguments were rejected, so fix them and rerun. Exit 4 from `friday` means this machine's `date` does no date arithmetic: stop and report it, because a hand-picked Friday is exactly what goes wrong across a month or year boundary. Done when both page names and that Friday date are known.
|
||||
3. Fill `templates/log-entry.md` with the ten facts of this one task and save it to a file. Done when that file holds exactly one entry.
|
||||
4. Run `tools/worklog-pending.sh merge {HASH} {entry file}`. It prints `MERGED=` (pending content in time order, then this task's entry), `CLAIM=` (the pending files it took) and `PENDING=` (how many). Pending content was written by an earlier stage that ended without a work log, so it belongs in **this** write.
|
||||
|
||||
| Exit | Do |
|
||||
| --- | --- |
|
||||
| 0 | Carry on with `MERGED` and `CLAIM`. `PENDING=0` is normal and still exit 0 |
|
||||
| 1 | A read or write under `$JSC_HOME/worklog-pending` failed. Stop and report the path from the message; nothing was deleted, so a rerun loses nothing |
|
||||
| 2 | The `{HASH}` is not 8 uppercase alphanumerics, or the entry file argument is missing. Fix the argument and rerun from step 1 |
|
||||
|
||||
Done when `MERGED` and `CLAIM` are known.
|
||||
5. Read `PAGE` via `jsc-gitea:wiki`, and branch on the exit code the underlying `gitea.sh wiki-get` returned. **Only exit 4 means the page is not there yet.** Reading any other code as "it does not exist" builds a fresh page from `templates/log-entry.md` and appends to that — which replaces the whole existing work log with this one entry, and no entry on it can be recovered from the wiki afterwards.
|
||||
|
||||
| Exit | Do |
|
||||
| --- | --- |
|
||||
| 0 | The existing content is in hand. Append the whole `MERGED` content at the end of it, and leave every existing entry byte for byte as it was. Never rebuild the page from the template on this code |
|
||||
| 4 | The page really is absent. Create it from the structure in `templates/log-entry.md`, then append `MERGED` |
|
||||
| 7 | The key is invalid or lacks permission, so the old content is unknown. Stop and report the key problem, write nothing and create no page — a page created here would take the place of a log that is still on the server |
|
||||
| 8 | Some other API failure. Stop and report that status, write nothing and create no page. Retry only after the API is back |
|
||||
|
||||
A failed write stops the run and goes to step 7 as a failure — never report the page as written when it was not. Done when every entry in `MERGED` is on `PAGE`, every entry that was already there is still there, and any 4 / 7 / 8 branch was followed as stated.
|
||||
6. Update `CONTENTS` in the same pass (apply `templates/log-contents.md`; add the row if missing, otherwise refresh its 條目數 and 最後更新). Its read branches exactly as step 5 does: only exit 4 creates the directory page from the template, while 7 and 8 stop the run rather than rebuild a directory whose other rows were never read. Touch no row that belongs to another page. Done when the row for `PAGE` carries this week's Friday date from step 2 and every other row is unchanged.
|
||||
7. Close the pending area on the result of steps 5 and 6: `tools/worklog-pending.sh commit {HASH} {CLAIM}` after both succeeded, or `tools/worklog-pending.sh abort {HASH} {CLAIM}` after either failed. `abort` keeps every pending file for the retry, so keep the entry file too and rerun from step 4.
|
||||
|
||||
| Exit | Do |
|
||||
| --- | --- |
|
||||
| 0 | Report the printed count. This is the only ending that clears pending content |
|
||||
| 1 | A pending file or the claim list could not be removed. Report the path and say the pending area still holds content, so the next run will merge it again — duplicate entries on `PAGE` are the thing to watch for |
|
||||
| 2 | The claim path is not the one `merge` produced, or it points outside this `{HASH}`'s pending directory. Rerun from step 4 with the `CLAIM` value that `merge` printed; never pass a hand-written path |
|
||||
|
||||
Done when one of the two ran and its exit code was reported.
|
||||
|
||||
Reference in New Issue
Block a user