feat(link): 連結一律寫成 [文字](絕對網址),寫入前先驗證連得到
取消 [[頁名]] 與 [[顯示文字|頁名]] 兩種同 wiki 寫法,不再分「同存取庫」與 「跨存取庫」兩條規則。那種寫法只在自己那個 wiki 內解析,寫錯不報錯,畫面上 看起來像普通文字或死連結,巡不到也修不了。 連結寫進頁面前先過 jsc-gitea 的 link-check.sh,結束碼 0 才寫。驗證一律走 API, 不看網頁狀態碼:私有存取庫的網頁網址對未登入請求一律回 404,拿狀態碼判會把 好連結判成壞的。認證失敗回 7,與死連結的 1 分開,免得金鑰一過期就把還在的頁 整批判死。
This commit is contained in:
+12
-1
@@ -11,7 +11,8 @@ Close the loop on skill runs: record what a run taught you, consult it before th
|
||||
|
||||
- Directory page: `LEARN_CONTENTS`. Content page: `LEARN_{HASH}`, one page per repository.
|
||||
- The two pages live in different wikis. `LEARN_{HASH}` goes to `jsc-gitea/tools/gitea.sh wiki-repo LEARN`; `LEARN_CONTENTS` goes to `gitea.sh wiki-repo CONTENTS` (`JSC_WIKI_REPO_CONTENTS`, then `JSC_WIKI_REPO`, then exit 3), which never falls back to the LEARN repo. Exit 3 on either hands the question to `jsc-gitea:wiki`, which owns the resolution order and the wording; exit 2 means the type argument was misspelled, so fix it and rerun.
|
||||
- Because they sit in different wikis, the directory row links the lesson page by the absolute URL from `gitea.sh wiki-url <LEARN repo> LEARN_{HASH}`. `[[LEARN_{HASH}]]` resolves only inside one wiki and would dead-link from the directory. `wiki-url` exit 4 means the lesson page is not written yet, so write it first; exit 5 means the page carries no `html_url`, so stop and report it and never assemble the URL by hand; exit 7 or 8 means the token or the API failed, so stop and report that status.
|
||||
- Every link this skill writes takes the shape `[{text}]({absolute URL})`. The directory row links the lesson page as `[LEARN_{HASH}](<url>)`, with `<url>` from `gitea.sh wiki-url <LEARN repo> LEARN_{HASH}` — never assembled by hand, and never the same-wiki `[[...]]` form, which resolves inside one wiki only and dead-links from the directory without reporting an error. `wiki-url` exit 4 means the lesson page is not written yet, so write it first; exit 5 means the page carries no `html_url`, so stop and report it and never assemble the URL by hand; exit 7 or 8 means the token or the API failed, so stop and report that status.
|
||||
- Check every link before it reaches a page: `jsc-gitea/tools/link-check.sh {url}...`. Only exit 0 permits the write.
|
||||
- Compute `{HASH}` from `{owner}/{repo}` with `jsc-gitea/tools/hash-id`. It prints the full 40-character uppercase SHA-1 — no truncation and no prefix rewrite, so never shorten it. Exit 1 means no SHA-1 helper on this machine: stop and report that `sha1sum` or `shasum` has to be installed, and never hand-compute the hash. Exit 2 means the input was empty, so fix the `{owner}/{repo}` parse and rerun.
|
||||
- All wiki reads and writes go through `jsc-gitea:wiki`, except the `LEARN_CONTENTS` row, which goes through `jsc-gitea/tools/wiki-contents.sh`.
|
||||
|
||||
@@ -41,6 +42,16 @@ Run after a skill run that produced a reusable lesson.
|
||||
| 7 | The token is invalid or lacks permission, so the old rows are unknown. Stop and report the token problem, and create no page |
|
||||
| 8 | Some other API failure. Stop and report that status, and create no page |
|
||||
|
||||
- Check the row's link before writing it. Feed the `wiki-url` output to `jsc-gitea/tools/link-check.sh`; it prints one `{OK|DEAD|SKIP}<TAB>{url}<TAB>{note}` line per URL and resolves Gitea URLs through the API, because a private repo answers a logged-out web request with 404 and would fail a page that is there.
|
||||
|
||||
| Exit | Do |
|
||||
| --- | --- |
|
||||
| 0 | Every link answered. Write the row |
|
||||
| 1 | At least one link is DEAD. Write nothing and report the DEAD lines to the caller |
|
||||
| 2 | No URL reached the script. Pass the URLs and rerun |
|
||||
| 3 | The list holds a Gitea URL but `GITEA_HOST` is unset. Set it and rerun; never skip the check |
|
||||
| 7 | The Gitea token was rejected (HTTP 401/403). Stop and report the token problem. A rejected token makes live pages look missing, and one batch judged on that answer wipes out links that still work |
|
||||
|
||||
- Update `LEARN_CONTENTS` in the same pass, and let `jsc-gitea/tools/wiki-contents.sh` do the row work — never hand-edit the directory page. Build one file holding the single row from `templates/learn-contents.md` (the repository name, the absolute link from `gitea.sh wiki-url <LEARN repo> LEARN_{HASH}`, and the update time), then run:
|
||||
|
||||
`jsc-gitea/tools/wiki-contents.sh upsert LEARN 1 "{owner}/{repo}" {row file} templates/learn-contents.md`
|
||||
|
||||
+11
-1
@@ -74,8 +74,18 @@ Write through `jsc-gitea:wiki`:
|
||||
- Repo: the REPORT repo from step 2, line 4. It hosts the content page only; `REPORT_CONTENTS` goes to the CONTENTS repo instead.
|
||||
- Page: `REPORT_` plus `gitea.sh hash-id "{owner}/{repo}/{period}"`. Here `{owner}/{repo}` is **the REPORT wiki repo itself** — the value `gitea.sh wiki-repo REPORT` printed — and not the code repo the logs came from. Every other page in this skill set hashes the code repo; this one page does not, because a report spans every code repo whose logs landed in the range, so no single code repo names it. Feed `hash-id` the exact string `{REPORT wiki owner}/{REPORT wiki repo}/{period}`, with `{period}` being the literal `daily`, `weekly`, `monthly` or `yearly` — so year, month, week and day each get their own page. `hash-id` prints the full 40-character uppercase SHA-1: use it whole, never shortened and never prefixed.
|
||||
- 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.
|
||||
- Check every link before it goes on a page — the ones inside the new section and the row's link alike: `jsc-gitea/tools/link-check.sh {url}...`. It prints one `{OK|DEAD|SKIP}<TAB>{url}<TAB>{note}` line per URL and resolves Gitea URLs through the API, because a private repo answers a logged-out web request with 404 and would fail a page that is there. Only exit 0 permits the write.
|
||||
|
||||
| Exit | Do |
|
||||
| --- | --- |
|
||||
| 0 | Every link answered. Write the section, or the row |
|
||||
| 1 | At least one link is DEAD. Write nothing and report the DEAD lines to the caller |
|
||||
| 2 | No URL reached the script. Pass the URLs and rerun |
|
||||
| 3 | The list holds a Gitea URL but `GITEA_HOST` is unset. Set it and rerun; never skip the check |
|
||||
| 7 | The Gitea token was rejected (HTTP 401/403). Stop and report the token problem. A rejected token makes live pages look missing, and one batch judged on that answer wipes out links that still work |
|
||||
|
||||
- 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` with `jsc-gitea/tools/wiki-contents.sh` — never hand-edit the directory page. It sits in the CONTENTS repo, not the REPORT repo, so the row links the report page by the absolute URL from `gitea.sh wiki-url <REPORT repo> REPORT_{HASH}`; `[[REPORT_{HASH}]]` resolves only inside one wiki and would dead-link from here. Build one file holding the single row from `templates/report-contents.md` (the absolute link, the bare `{HASH}`, the period, the newest label, the section count and the update time), then run:
|
||||
- Refresh the page's row in `REPORT_CONTENTS` with `jsc-gitea/tools/wiki-contents.sh` — never hand-edit the directory page. It sits in the CONTENTS repo, not the REPORT repo, so the row links the report page as `[REPORT_{HASH}](<url>)`, with `<url>` from `gitea.sh wiki-url <REPORT repo> REPORT_{HASH}`. Every link on the report body and on this row takes that same `[{text}]({absolute URL})` shape; the same-wiki `[[...]]` form resolves inside one wiki only and dead-links from here without reporting an error. Build one file holding the single row from `templates/report-contents.md` (the absolute link, the bare `{HASH}`, the period, the newest label, the section count and the update time), then run:
|
||||
|
||||
`jsc-gitea/tools/wiki-contents.sh upsert REPORT 2 "{HASH}" {row file} templates/report-contents.md`
|
||||
|
||||
|
||||
+18
-4
@@ -27,14 +27,16 @@ Rows 3, 4, 5 and 6 each hit a different source and none of them reads another's
|
||||
| --- | --- | --- |
|
||||
| 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. `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 「無」 |
|
||||
| 3 | Plan name | Link to the plan page in the shape `[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}` — never assemble it by hand, and never use the same-wiki `[[...]]` form: PLAN and LOG may live in different wiki repos, and `[[...]]` resolves inside one wiki only. `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 | Link to the work package heading in the shape `[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 |
|
||||
| 9 | Difficulties and resolutions | One pair per line. Ask via `jsc-ask:ask` when the session does not show them |
|
||||
| 10 | PR target branch | Link to the PR page |
|
||||
| 10 | PR target branch | Link to the PR page in the shape `[{base branch}]({PR URL})` |
|
||||
|
||||
Every link in an entry is text plus an absolute URL — `[{text}]({url})` — with wiki URLs coming from `gitea.sh wiki-url`. The same-wiki `[[...]]` form is out: it resolves inside one wiki only, and a link that fails that way looks like ordinary text on the page instead of reporting an error.
|
||||
|
||||
The `{HASH}` in every page name above is computed with `jsc-gitea/tools/hash-id`, which prints the full 40-character uppercase SHA-1 of its input — no truncation to 8 characters and no prefix rewrite. A page name shortened by hand points at a page nobody else writes to.
|
||||
|
||||
@@ -65,10 +67,22 @@ The `{HASH}` in every page name above is computed with `jsc-gitea/tools/hash-id`
|
||||
| 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 |
|
||||
|
||||
Before the write, hand every URL that `MERGED` carries — plan page, work package heading, PR page — to `jsc-gitea/tools/link-check.sh {url}...`. It prints one `{OK|DEAD|SKIP}<TAB>{url}<TAB>{note}` line per URL and resolves Gitea URLs through the API, because a private repo answers a logged-out web request with 404 and would fail a page that is there. Only exit 0 permits the write.
|
||||
|
||||
| Exit | Do |
|
||||
| --- | --- |
|
||||
| 0 | Every link answered. Write the entries |
|
||||
| 1 | At least one link is DEAD. Write nothing, report the DEAD lines, and go to step 7 as a failure so the pending content survives |
|
||||
| 2 | No URL reached the script. Pass the URLs and rerun |
|
||||
| 3 | The list holds a Gitea URL but `GITEA_HOST` is unset. Set it and rerun; never skip the check |
|
||||
| 7 | The Gitea token was rejected (HTTP 401/403). Stop and report the token problem. A rejected token makes live pages look missing, and one batch judged on that answer wipes out links that still work |
|
||||
|
||||
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, and let `jsc-gitea/tools/wiki-contents.sh` do the row work — never hand-edit the directory page.
|
||||
|
||||
`LOG_CONTENTS` lives in the CONTENTS wiki repo that `gitea.sh wiki-repo CONTENTS` resolves (`JSC_WIKI_REPO_CONTENTS`, then `JSC_WIKI_REPO`), which is **not** the LOG repo of step 1 and never falls back to it. Because the two pages sit in different wikis, the row's link to the log page is the absolute URL from `gitea.sh wiki-url <LOG repo> LOG_{HASH}` — `[[LOG_{HASH}]]` resolves only inside one wiki and would dead-link from here. `wiki-url` exit 4 means the step 5 write has not landed yet, so stop and rerun step 5 before this one; exit 5 means the page carries no `html_url`, so stop and report it and never assemble the URL by hand; exit 7 or 8 means the token or the API failed, so stop and report that status.
|
||||
`LOG_CONTENTS` lives in the CONTENTS wiki repo that `gitea.sh wiki-repo CONTENTS` resolves (`JSC_WIKI_REPO_CONTENTS`, then `JSC_WIKI_REPO`), which is **not** the LOG repo of step 1 and never falls back to it. Because the two pages sit in different wikis, the row links the log page as `[LOG_{HASH}](<url>)`, with `<url>` from `gitea.sh wiki-url <LOG repo> LOG_{HASH}` — never the same-wiki `[[...]]` form, which resolves inside one wiki only and dead-links from here without reporting an error. `wiki-url` exit 4 means the step 5 write has not landed yet, so stop and rerun step 5 before this one; exit 5 means the page carries no `html_url`, so stop and report it and never assemble the URL by hand; exit 7 or 8 means the token or the API failed, so stop and report that status.
|
||||
|
||||
Put that URL through the step 5 `link-check.sh` gate before the upsert, with the same exit branches: only exit 0 writes the row, and a DEAD line stops the write and goes to step 7 as a failure.
|
||||
|
||||
Build one file holding the single row from `templates/log-contents.md` — the absolute link, the bare `{HASH}` of step 1, this week's Friday date from step 2, the entry count and the update time — then run:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user