feat(link): 連結一律寫成 [文字](絕對網址),寫入前先驗證連得到
取消 [[頁名]] 與 [[顯示文字|頁名]] 兩種同 wiki 寫法,不再分「同存取庫」與 「跨存取庫」兩條規則。那種寫法只在自己那個 wiki 內解析,寫錯不報錯,畫面上 看起來像普通文字或死連結,巡不到也修不了。 連結寫進頁面前先過 jsc-gitea 的 link-check.sh,結束碼 0 才寫。驗證一律走 API, 不看網頁狀態碼:私有存取庫的網頁網址對未登入請求一律回 404,拿狀態碼判會把 好連結判成壞的。認證失敗回 7,與死連結的 1 分開,免得金鑰一過期就把還在的頁 整批判死。
This commit is contained in:
@@ -17,7 +17,7 @@ The link is the only input. The output is one file that opens anywhere, with no
|
||||
- **Track C — destination.** Ask per the `jsc-ask:ask` rules where the file goes, proposing `./.jsc/html/{page-or-issue}.html`. State the impact scope: a path inside a repository gets committed unless it is ignored.
|
||||
|
||||
Completion condition: the markdown and the document title are in hand, exactly one kind key is chosen with the reason that produced it, the layout, style and source are reported, and the user has confirmed one output path.
|
||||
4. **Prepare the markdown — this step MUST run as a sub agent.** Convert `[[display|page]]` wiki links to absolute URLs from `wiki-url`; the renderer does not resolve them, so they would ship as literal brackets. Strip personal data — an exported file travels further than the page it came from. Leave everything else exactly as written; this step never rewrites the content. Completion condition: no `[[...]]` remains, and the diff against the source is limited to link conversion and personal-data removal.
|
||||
4. **Prepare the markdown — this step MUST run as a sub agent.** Links are written as `[text](absolute URL)`, so pages that follow the current rule need no conversion. An older page can still carry a wiki-internal link: turn it into an absolute URL from `wiki-url`, because the renderer does not resolve it and it would ship as literal brackets. Strip personal data — an exported file travels further than the page it came from. Leave everything else exactly as written; this step never rewrites the content. Completion condition: every link in the file is `[text](absolute URL)`, and the diff against the source is limited to link conversion and personal-data removal.
|
||||
5. Render: `tools/html-render.sh --markdown {file} --title {title} --layout {layout} --style {style} --source-url {absolute URL} --out {path}`. Route every exit code: 0 → the path it printed is the finished file; 1 → Gitea's renderer or the write failed, so report it and stop, with no half-rendered file left behind; 2 → a usage error or a missing markdown file, so fix the arguments and call again; 4 → the layout or style template file is gone, so report which pair was asked for and send the user to `jsc-gitea:html-style` rather than editing the configuration by hand. Completion condition: the file exists, and the report names its path, the layout, the style and where that pair came from.
|
||||
|
||||
## Rules
|
||||
|
||||
@@ -15,11 +15,11 @@ The wiki link is the only input. Everything else — repository, page name, host
|
||||
|
||||
Completion condition: the parse printed `kind=wiki` with `repo`, `page` and `host` known, **and** `GITEA_HOST` holds a value — both, or the run has stopped with the reason named.
|
||||
2. **Run these three tracks at the same time.** The label list and the board list depend on the repository only, not on the page, so they start in the same batch as the read rather than queueing behind the draft.
|
||||
- **Track A — read and draft.** Read the page with `jsc-gitea:wiki` (`wiki-get {repo} {page}`) and take its absolute URL from `wiki-url` in the same pass. Route the exit codes by that skill's table: 4 means the page does not exist, 7 means the key is invalid or lacks permission, 8 is any other API failure — all three stop this skill with the page name in the report. **Drafting MUST run as a sub agent.** Title: the page's first heading, or the page name when it has none. Body: the page content in Traditional Chinese, opening with a 「來源:{絕對網址}」 line so the issue points back at the wiki. Convert `[[display|page]]` links to absolute URLs (`wiki-url`), because `[[...]]` resolves only inside a wiki. Drop personal data — an issue is read by more people than a wiki page.
|
||||
- **Track A — read and draft.** Read the page with `jsc-gitea:wiki` (`wiki-get {repo} {page}`) and take its absolute URL from `wiki-url` in the same pass. Route the exit codes by that skill's table: 4 means the page does not exist, 7 means the key is invalid or lacks permission, 8 is any other API failure — all three stop this skill with the page name in the report. **Drafting MUST run as a sub agent.** Title: the page's first heading, or the page name when it has none. Body: the page content in Traditional Chinese, opening with a 「來源:{絕對網址}」 line so the issue points back at the wiki. Links are written as `[文字](絕對網址)`; a wiki-internal link left over from an older page becomes an absolute URL from `wiki-url`, because that form resolves only inside a wiki and an issue is not one. Drop personal data — an issue is read by more people than a wiki page.
|
||||
- **Track B — label list.** Run `tools/issue.sh labels {repo}`. Exit 1 means the label list could not be read: stop and report it, because the alternative is inventing labels. Exit 2 is a usage error — fix the arguments and call again.
|
||||
- **Track C — board list.** Run `tools/issue.sh projects {repo}`. Exit 3 means this Gitea has no board API — keep the board URL the script printed for step 4. Exit 1 means the call failed for another reason: report it and treat the board link as outstanding. Exit 2 is a usage error — fix the arguments and call again.
|
||||
|
||||
Completion condition: the title and body file exist with the source line and no `[[...]]` left in the body, the repository's label list is in hand or the run has stopped, and the board list is either in hand or recorded as unavailable.
|
||||
Completion condition: the title and body file exist with the source line and every link in the body written as `[文字](絕對網址)`, the repository's label list is in hand or the run has stopped, and the board list is either in hand or recorded as unavailable.
|
||||
3. **Labels come from what the repository already has.** Propose the fitting ones from track B's list with a reason each, and confirm per `jsc-ask:ask` rules — every option states its impact scope (a label drives filters and board rules, so a wrong one routes the work to the wrong queue). Turn the confirmed names into ids with `tools/issue.sh label-ids {repo} {names}`. Exit 4 means a name is not in the repository: go back to the list and pick again, never create the label to make the command pass. Exit 1 means the call failed — report it and stop. An empty label list, or nothing fitting: ask whether to create the issue with no label, and record that answer. **Never invent a label that the repository does not have.** Completion condition: the user has confirmed a label set — possibly empty — and its ids are resolved.
|
||||
4. **Project board.** Track C returned a board list: let the user pick one per `jsc-ask:ask` rules, attach it, and report the failure verbatim if the attach call is refused. Track C exited 3: say plainly that this Gitea has no board API, and hand the user the board URL the script printed so they can drag the issue in themselves. Completion condition: the issue is either attached to a board, or the report states in one line that the board link is still outstanding and who has to do it.
|
||||
5. Create the issue: `tools/issue.sh create {repo} {title} {body-file} [--labels {ids}]`. The script asks for confirmation before it writes, so expect that prompt and hand the user the title, the labels and the board it is about to apply. Exit 0: report the `index=` and `url=` it prints. Exit 1 means no issue was created — report that plainly, and hand back the path of the drafted body file so the draft is not lost. Exit 2 is a usage error, usually a body file that is not there — fix the arguments and call again. Completion condition: the issue URL is reported to the user together with the labels applied and the board status from step 4, or the report states that no issue was created and where the draft is.
|
||||
|
||||
+12
-4
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: wiki
|
||||
description: Read or write a Gitea wiki page through tools/gitea.sh, tools/hash-id and tools/page-name.sh. Resolve the wiki repo per page type with JSC_WIKI_REPO_{TYPE} first, then JSC_WIKI_REPO, and ask only when neither is set - every *_CONTENTS page resolves through type CONTENTS and is updated with tools/wiki-contents.sh, and {HASH} is the full 40-char uppercase SHA-1 from tools/hash-id. Page content is chart-first - prefer mermaid diagrams and markdown tables over plain prose. Callers are jsc-ask, jsc-sdlc, jsc-log, jsc-hooks (ERROR), jsc-cli (CHECK), jsc-meta (SKILLSET, TOOLING) and jsc-assist (MONITOR). Use for any wiki page in the skill set; not for repo code files.
|
||||
description: Read or write a Gitea wiki page through tools/gitea.sh, tools/hash-id and tools/page-name.sh. Resolve the wiki repo per page type with JSC_WIKI_REPO_{TYPE} first, then JSC_WIKI_REPO, and ask only when neither is set - every *_CONTENTS page resolves through type CONTENTS and is updated with tools/wiki-contents.sh, and {HASH} is the full 40-char uppercase SHA-1 from tools/hash-id. Page content is chart-first - prefer mermaid diagrams and markdown tables over plain prose, and every link is written as [text](absolute URL) that tools/link-check.sh passed before the write. Callers are jsc-ask, jsc-sdlc, jsc-log, jsc-hooks (ERROR), jsc-cli (CHECK), jsc-meta (SKILLSET, TOOLING) and jsc-assist (MONITOR). Use for any wiki page in the skill set; not for repo code files.
|
||||
---
|
||||
|
||||
# wiki — read and write Gitea wiki pages
|
||||
@@ -27,8 +27,9 @@ Different page types can live in different `{owner}/{repo}` repos, classified by
|
||||
| update a contents page | `tools/wiki-contents.sh upsert {TYPE} {key-col} {key} {row-file} [template-file]` — resolves the CONTENTS repo, replaces the row whose key column matches, appends when none does, writes the whole page back. `{key-col}` is the column's 1-based position number, not the column name |
|
||||
| check a page name | `tools/page-name.sh check {page}` — the single source of the page-name pattern; `tools/page-name.sh regex` prints it |
|
||||
| move pages to the current rules | `tools/migrate-wiki.sh [--apply] [--key {key}]...` — prints the mapping table and the orphan list; writes only with `--apply` |
|
||||
| check links before a write | `tools/link-check.sh {url}...` — prints `{OK\|DEAD\|SKIP}<TAB>{url}<TAB>{reason}` per URL; exit 0 means every link is reachable |
|
||||
|
||||
Contents pages and content pages no longer share a repo. Link between them — and between any two different types — with the absolute URL from `wiki-url`. Keep `[[display|page]]` (display text on the LEFT) for two pages that resolve to the same repo: contents page to contents page, or same-type content page to same-type content page. Full rules and the direction trap: `references/wiki-links.md`.
|
||||
Every link in a page is written as `[text](absolute URL)`, and the URL comes from `wiki-url` — one form for every target, inside this wiki or not. Every link goes through `tools/link-check.sh` before the page is written. Full rules, and why `[[...]]` was dropped: `references/wiki-links.md`.
|
||||
|
||||
## Exit codes
|
||||
|
||||
@@ -40,7 +41,7 @@ Route every `tools/gitea.sh` call in this skill on its exit code. A code with no
|
||||
| 2 | usage error, or a page type outside the allowed list | fix the arguments, then call again; never repeat the same call unchanged |
|
||||
| 3 | `wiki-repo`: neither `JSC_WIKI_REPO_{TYPE}` nor `JSC_WIKI_REPO` is set | go to step 3 and ask |
|
||||
| 4 | HTTP 404: `wiki-get` and `wiki-url` found no such page, or `wiki-delete` found nothing to delete | for a read the caller expects to succeed, stop and report the page name; this is the **only** code that opens the create path of rule 4 — write the page from the template instead of appending. For `wiki-delete` it means the page is already gone: report it and move on, do not retry |
|
||||
| 5 | `wiki-url`: the page exists but the API returned no `html_url` | stop and report it. Link inside the same wiki with `[[display\|page]]`; a cross-repo link has no absolute URL to point at, so do not fabricate one |
|
||||
| 5 | `wiki-url`: the page exists but the API returned no `html_url` | stop and report it. There is no second link form to fall back on, and a hand-built path is not a substitute — never fabricate the URL |
|
||||
| 7 | HTTP 401 or 403 after the tea-token retry: the key is invalid or lacks permission | **stop the whole operation and report the key problem.** Never read this as an empty or missing page, and never take the create path of rule 4: writing a fresh page over one you could not read destroys the record that is still there |
|
||||
| 8 | any other API failure, HTTP status in the message | stop and report that status; call again only after the cause is fixed |
|
||||
|
||||
@@ -63,6 +64,11 @@ Every code below gets its own branch. Nothing here is retried unchanged.
|
||||
| | 4 | the page is not there and no template was given | supply the template for that page type, then call again |
|
||||
| | 7 | the key is invalid or lacks permission | stop the whole operation and report the key problem; create no page |
|
||||
| | 8 | any other API failure | stop and report the status |
|
||||
| `tools/link-check.sh` | 0 | every link is reachable | write the page; this is the only code that opens `wiki-put` |
|
||||
| | 1 | at least one link is dead | do not write. Report the `DEAD` rows verbatim, fix or drop those links, then check again |
|
||||
| | 2 | usage error: no URL was given | fix the arguments, then call again; never skip the check because the list looked empty |
|
||||
| | 3 | the list holds a Gitea URL but `GITEA_HOST` is not set | set `GITEA_HOST` and call again. Never write the page unchecked |
|
||||
| | 7 | HTTP 401 or 403: the key is invalid or lacks permission | stop the whole operation and report the key problem. Those pages are not dead — treating them as dead deletes or rewrites links to pages that are still there |
|
||||
| `tools/migrate-wiki.sh` | 0 | every page moved, or the preview found nothing to move | report the mapping table |
|
||||
| | 1 | at least one page failed to move | report the failure list; the old pages of the failed entries stay in place |
|
||||
| | 2 | usage error, including an unconfigured CONTENTS repo | fix the arguments or set `JSC_WIKI_REPO_CONTENTS`, then call again |
|
||||
@@ -81,4 +87,6 @@ Every code below gets its own branch. Nothing here is retried unchanged.
|
||||
5. Write all wiki content in UTF-8 Traditional Chinese, per the STE100 output rule.
|
||||
6. Prefer visual forms for page content: use mermaid diagrams (flowchart, sequence, gantt, pie) and markdown tables wherever the information allows. Prose is capped at 3 sentences per section, and a sentence stays only when neither a mermaid diagram nor a markdown table can carry the same information.
|
||||
7. `tools/gitea.sh` retries once with the tea CLI login token when `GITEA_TOKEN` is missing or the response is 401/403. Report a failure only after that retry also fails.
|
||||
8. `wiki-delete` removes a page for good. Call it only from `tools/migrate-wiki.sh --apply`, or when the user has asked for that exact page to go. In a migration the delete comes last: write the new page, read it back, then delete the old one.
|
||||
8. **Rule A — every link is written as `[text](absolute URL)`.** That is the only form. `[[page]]` and `[[display|page]]` are gone, and there is no longer a same-repo case that keeps them. The URL always comes from `tools/gitea.sh wiki-url {owner}/{repo} {page}`, never from a path built by hand. Why: `[[...]]` resolves only inside the current wiki, so a cross-repo link silently lands on a same-named page in this one — and it fails as plain text or a dead link, with nothing to catch it. Contents pages and content pages already live in different repos, so keeping two forms would mean judging, link by link, which repo each end resolves to.
|
||||
9. **Rule B — check every link before the write.** Run `tools/link-check.sh {url}...` over every link that is going into the page. Exit 0 is the only code that opens `wiki-put`. Exit 1 means at least one link is dead: write nothing, and hand the caller the `DEAD` rows. Exit 7 means the key failed, not that the pages are gone — stop and report the key problem. Checking after the write is not the same thing: the dead link is already published, and the next reader follows it.
|
||||
10. `wiki-delete` removes a page for good. Call it only from `tools/migrate-wiki.sh --apply`, or when the user has asked for that exact page to go. In a migration the delete comes last: write the new page, read it back, then delete the old one.
|
||||
|
||||
Reference in New Issue
Block a user