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.
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 upserted by tools/wiki-contents.sh as one H2 block per record, and {HASH} is the full 40-char uppercase SHA-1 from tools/hash-id. A contents page carries no markdown table - one H2 block per record, headed by that record's content-page name with one bullet per field - while a content page is chart-first, preferring 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
# wiki — read and write Gitea wiki pages
@@ -24,7 +24,7 @@ Different page types can live in different `{owner}/{repo}` repos, classified by
| 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) |
| 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 |
| 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` |
| 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 |
| update a contents page | `tools/wiki-contents.sh upsert {TYPE} {key-col} {key} {entry-file} [template-file]` — resolves the CONTENTS repo, replaces the `## {key}` block, appends when the page holds no such heading, writes the whole page back. `{entry-file}` is that record's whole H2 block. `{key-col}` only matters while the old page is still a markdown table: it is the 1-based position of the column that carries the record's identity, and the script converts such a page to H2 blocks before the upsert, taking each heading from that cell's link URL — its last path segment, percent-decoded — or from the cell's plain text when the cell holds no link. On that conversion, a supplied `{template-file}` also replaces the page's H1 and `>` intro with the template's own, because a conversion moves the table alone and the old intro keeps describing rows; an already-converted page keeps its intro untouched, and so does a conversion run without a template |
| 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 |
| 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` |
| 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 |
| 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 |
@@ -57,8 +57,8 @@ Every code below gets its own branch. Nothing here is retried unchanged.
| `tools/page-name.sh` | 0 | the page name follows the pattern | continue with that 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 |
| | 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 |
| | 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 |
| `tools/wiki-contents.sh` | 0 | the block 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 |
| | 1 | the page content could not be built, or the write failed | stop and report; fix the page or the entry before calling again. A missing `## {key}` is not this code — that path appends |
| | 2 | usage error, or an unknown page type | fix the arguments, then call 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` |
| | 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 |
| | 4 | the page is not there and no template was given | supply the template for that page type, then call again |
@@ -89,7 +89,7 @@ This skill is called by almost every other one, so its status is what the caller
| `ok` | The read returned the page, or the write landed: `link-check.sh` exited 0, the confirmation was given, and `wiki-put` exited 0 |
| `ok` | The read returned the page, or the write landed: `link-check.sh` exited 0, the confirmation was given, and `wiki-put` exited 0 |
| `blocked` | The location could not be resolved, so nothing was read and nothing was written: `GITEA_HOST` holds no value and the user gave none, or `wiki-repo` exited 3 and the user supplied no `{owner}/{repo}` for that page type |
| `blocked` | The location could not be resolved, so nothing was read and nothing was written: `GITEA_HOST` holds no value and the user gave none, or `wiki-repo` exited 3 and the user supplied no `{owner}/{repo}` for that page type |
| `failed` | The operation ran and broke. **Exit 7 belongs here**: the key is invalid or lacks permission, so the whole operation stopped, and that is a failure, never an absent page. Exit 8, a `wiki-put` that did not land, a `link-check.sh` exit 1 that refused the write, and a `hash-id` or `page-name.sh` rejection all sit here too |
| `failed` | The operation ran and broke. **Exit 7 belongs here**: the key is invalid or lacks permission, so the whole operation stopped, and that is a failure, never an absent page. Exit 8, a `wiki-put` that did not land, a `link-check.sh` exit 1 that refused the write, and a `hash-id` or `page-name.sh` rejection all sit here too |
| `degraded` | The content page landed and the contents page did not — `wiki-put` on `{TYPE}_{HASH}` exited 0, then `wiki-contents.sh upsert` exited 3 with no CONTENTS repo configured, or exited 1 on a page holding no markdown table. The record exists but nothing indexes it, so the next reader will not find it. A migration that moved some pages and left orphans or occupied destinations behind sits here as well |
| `degraded` | The content page landed and the contents page did not — `wiki-put` on `{TYPE}_{HASH}` exited 0, then `wiki-contents.sh upsert` exited 3 with no CONTENTS repo configured, or exited 1 because the page content could not be built or the write did not land. The record exists but nothing indexes it, so the next reader will not find it. A migration that moved some pages and left orphans or occupied destinations behind sits here as well |
| `aborted` | The premise did not hold or the user stopped it: `write-confirm.sh` was refused before a write or a delete, or the caller asked for a page type outside the allowed list and the run stopped at `wiki-repo` exit 2 |
| `aborted` | The premise did not hold or the user stopped it: `write-confirm.sh` was refused before a write or a delete, or the caller asked for a page type outside the allowed list and the run stopped at `wiki-repo` exit 2 |
Completion condition: exactly one `skill-end` line was recorded for this run, or the script was absent and the run finished without it.
Completion condition: exactly one `skill-end` line was recorded for this run, or the script was absent and the run finished without it.
@@ -98,14 +98,14 @@ Completion condition: exactly one `skill-end` line was recorded for this run, or
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.
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.
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.
3. **A contents page (`*_CONTENTS`) is one H2 block per record, never a table.** The H2 heading is that record's key, written as the content page's own name (`{TYPE}_{HASH}`) — no link, no URL, no prefix, no date. Every field is one bullet under it, `- {field}:{value}`, full-width colon, one bullet per field including the key's own. Update it with`tools/wiki-contents.sh upsert {TYPE} {key-col} {key} {entry-file} [template-file]`, where `{entry-file}` holds that whole H2 block. The script reads the page, converts a page still holding a markdown table into H2 blocks first, replaces the block whose heading equals `{key}`, appends the block when no heading matches, and writes the whole page back through the same confirmation. `{key-col}` is used only by that conversion: it is the 1-based position of the old table's identity column, and it is ignored once the page is already in block form. That conversion takes the heading from the identity cell's markdown link — the URL's last path segment, percent-decoded, because the link text is often a work-package or plan name rather than the page name — and from the cell's plain text, backticks stripped, only when the cell holds no link; it never checks the result against the page-name pattern, since old timestamped names, new 40-char names, and plain `{owner}/{repo}` identities all appear online. **That conversion is also the one moment the intro may be rewritten:** when `{template-file}` is given, everything before the first `## ` — the H1, the `>` intro, the blank lines between them — is replaced by the template's own preamble, taken the same way and carrying none of the template's demo blocks. Why: the conversion moves the table and leaves the prose, so an intro still saying "one row per repository" outlives the rows it describes, and the template holds the canonical wording. A page already in block form keeps its intro exactly as its owner wrote it — that call only updates its own record — and a conversion run without a template keeps the old intro, there being no canonical copy to install. 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.
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.
- **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.
- **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.
- **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.
- `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.
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.
6. **Chart-first applies to content pages (`*_{HASH}`) only.** On a content page, prefer visual forms: 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.**A contents page (`*_CONTENTS`) always takes the H2-heading-plus-bullets form of rule 3 instead** — no table, and no diagram, whatever the field count. Why: the heading is the key the upsert matches on, so the layout is fixed by the tool, not by which form reads better.
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.
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. **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.
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.
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.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.