--- 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. --- # wiki — read and write Gitea wiki pages Every wiki operation in the jsc skill set goes through this skill. One entry point, one permission path. ## Resolve the wiki location Different page types can live in different `{owner}/{repo}` repos, classified by the page-name prefix. 1. **Host gate.** Confirm `GITEA_HOST` holds a value in the current shell. When it is missing, ask for it per the `jsc-ask:ask` rules before any `tools/gitea.sh` call that reaches the API; otherwise the first thing the user sees is the script's `GITEA_HOST is required` line instead of a decision-tree question. `GITEA_TOKEN` needs no inventory here — the script resolves it, retries once with the tea CLI login token, and exits 7 when neither works. Done when `GITEA_HOST` holds a value. 2. Run `tools/gitea.sh wiki-repo {TYPE}`. Allowed types are `QUESTION`, `PLAN`, `ANALYZE`, `DELIVER`, `MAINTAIN`, `REPO`, `LOG`, `LEARN`, `ERROR`, `CHECK`, `REPORT`, `SKILLSET`, `TOOLING`, `MONITOR`, and `CONTENTS`. **Every `*_CONTENTS` page resolves through `CONTENTS` — all contents pages live in one dedicated repo, so never pass a contents page its own prefix. A content page (`*_{HASH}`) resolves through its own type.** The script reads `JSC_WIKI_REPO_{TYPE}` first and `JSC_WIKI_REPO` second, straight from the inherited environment, so take no separate inventory of those two variables. Never borrow another type's repo. Done when the command has printed exactly one `{owner}/{repo}`, or exited 3 and sent this page type to step 3, or exited 2 on a type outside the list above and stopped the run. 3. On exit 3 (neither variable is set), ask the user for that page type's `{owner}/{repo}` per the `jsc-ask:ask` rules, and suggest setting `JSC_WIKI_REPO_{TYPE}` (can differ per type, and `JSC_WIKI_REPO_CONTENTS` holds every contents page) or `JSC_WIKI_REPO` (shared default). Done when the user has supplied one `{owner}/{repo}` for that page type. ## Operations | Action | Command | | --- | --- | | list pages | `tools/gitea.sh wiki-list {owner}/{repo}` | | read page | `tools/gitea.sh wiki-get {owner}/{repo} {page}` | | write page | write the content to a temp file first, then `tools/gitea.sh wiki-put {owner}/{repo} {page} {file}` (asks for confirmation first, then creates or updates) | | delete page | `tools/gitea.sh wiki-delete {owner}/{repo} {page}` — asks for the same confirmation as a write. Only a migration or an explicit user request may call it | | page URL | `tools/gitea.sh wiki-url {owner}/{repo} {page}` — the page's absolute URL, taken from the API's `html_url` | | 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` | 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`. ## Exit codes Route every `tools/gitea.sh` call in this skill on its exit code. A code with no branch below stops the run and gets reported as it is. | Code | Meaning | What this skill does | | --- | --- | --- | | 0 | success | use the output | | 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 | | 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 | ### Helper scripts Every code below gets its own branch. Nothing here is retried unchanged. | Script | Code | Meaning | What this skill does | | --- | --- | --- | --- | | `tools/hash-id` | 0 | the full 40-char uppercase hash | use it as `{HASH}` | | | 1 | this machine has neither `sha1sum` nor `shasum` | stop, report that one of them has to be installed, compute no hash by hand | | | 2 | no text given, or the text was empty | fix the key you passed, then call again; never fall back to a hand-made page name | | `tools/page-name.sh` | 0 | the page name follows the pattern | continue with that page name | | | 1 | the page name breaks the pattern | stop and report the name; build the correct one instead of writing to a wrong page | | | 2 | usage error | fix the arguments, then call again | | `tools/wiki-contents.sh` | 0 | the row was updated or added | report which of the two, and the page | | | 1 | the write failed, or the page held no markdown table | stop and report; fix the page or the row before calling again | | | 2 | usage error, or an unknown page type | fix the arguments, then call again | | | 3 | the CONTENTS repo is not configured | go to step 3 and ask for `JSC_WIKI_REPO_CONTENTS` | | | 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/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 | | | 3 | something needs manual handling: an orphan page, a page that links to a moved page without being moved itself, or a destination page that already holds content | report those lists and hand them to the user; guess no key, and rewrite no link the script left alone | ## Rules 1. Page names must follow the wiki naming table in the skill guidelines (see `jsc-meta/references/guidelines.md`). Check any page name you build with `tools/page-name.sh check {page}` before it reaches an API call. 2. Use `tools/hash-id` for `{HASH}` values. It returns the full 40 uppercase SHA-1 hex chars — no truncation, no prefix. Never compute a hash by hand: a hand-made page name lands the content on a page nobody else reads. 3. To update a contents page (`*_CONTENTS`), run `tools/wiki-contents.sh upsert {TYPE} {key-col} {key} {row-file} [template-file]`, where `{key-col}` is the column's 1-based position number, not the column name. It reads the page, replaces the row whose key column equals the key, appends the row when no line matches, and writes the whole page back through the same confirmation. Never overwrite entries owned by others. Whether the page may be created from the template instead is decided by rule 4, and by nothing else. 4. **Only exit 4 means the page is not there yet — this rule binds every "create it if it does not exist" path, without exception.** It is not limited to contents pages: a content page (`*_{HASH}`), a work log, an error page, a report, any page at all, follows the same branch. - **Correct branch.** Read the page with `wiki-get`. Exit 0 means the page exists, so append or modify the content that came back and `wiki-put` the whole page. Exit 4 (HTTP 404) is the one and only code that permits creating a new page from the template. - **Exit 7 and exit 8 abort.** Exit 7 (HTTP 401 or 403) and exit 8 (any other API failure) both mean the old content is unknown, never that the page is missing. Stop the operation and report the exit code with its cause. Create no page, write nothing, and do not retry the same call unchanged. - **Why.** Wiki writes in this skill set are append-not-overwrite, and that semantics rests entirely on reading the old page back first. Reading a 401 as a 404 makes the caller believe it holds a brand-new page and `wiki-put` a fresh template over a live one, and the whole earlier record is gone — the write carries no merge and no backup. - `tools/wiki-contents.sh` implements exactly this branch for contents pages and reports the same codes. 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.