@@ -37,13 +37,13 @@ Inside one work session this skill is the only writer of `QUESTION_{HASH}` and `
2. After each Q&A round, hand both wiki writes to one sub agent, content page first and directory page second, so the directory never links a page that failed to write.
-`QUESTION_{HASH}` is written through `jsc-gitea:wiki` — it owns the `JSC_WIKI_REPO_QUESTION` → `JSC_WIKI_REPO` resolution and the tea-token fallback, which a hand-rolled Gitea API call loses. Apply `templates/question-record.md`: append this round as a new section, keep every earlier section, and open the section with the user's original intent (why this questioning round happened), which lets a later reader judge why the user chose as they did and whether the answer still applies. `QUESTION_{HASH}` belongs to this one repository, which is why appending a section is the right shape there. Write every link in the section as `[{text}]({url})`, and take each wiki `{url}` from `jsc-gitea/tools/gitea.sh wiki-url` — never assemble a path by hand.
- Verify before writing: hand every link of the new section to `jsc-gitea/tools/link-check.sh` and branch on its exit code. 0: every link answers, so write the section. 1: at least one link is DEAD, so write nothing and report the DEAD lines to the calling skill — a dead link on a record page reads as a real page and nobody finds it again. 2: no URL reached the script, so pass the links again. 3: `GITEA_HOST` is unset, so report that it must be set and run the check again; never write a link that skipped the check. 7: the Gitea key failed, so stop and report the key problem — a failed key makes live pages look dead. A section carrying no link goes straight to the write. Done when the check exited 0 and the section is written, or nothing was written and the report names the failing links or the exit code.
-`QUESTION_CONTENTS` is written by one call to `jsc-gitea/tools/wiki-contents.sh upsert QUESTION 1 {owner}/{repo} {row-file} templates/question-contents.md`. `key-col` is the 1-based column index, not a column name, and column 1 of `QUESTION_CONTENTS` is 存取庫名稱 — that cell holds the bare `{owner}/{repo}` text. The script compares the whole cell, so pass the key exactly as the row file writes it. The row file holds this repository's single row, and its 問詢紀錄 cell is written as `[QUESTION_{HASH}]({url})`, where `{url}` is the absolute URL printed by `jsc-gitea/tools/gitea.sh wiki-url {question-repo} QUESTION_{HASH}`. Take that URL from the command only; never assemble a path by hand. The two pages sit in different repositories — the directory page in the `CONTENTS` repo, the record page in the `QUESTION` repo — so only an absolute URL crosses from one to the other. Always pass the template argument. The script owns the read-merge-write of that shared directory: it upserts this one row and touches no other repository's row, so do not read the page and rebuild it by hand.
- Branch on `wiki-url`'s exit code before the row is built, because a URL that never arrived leaves that cell silently empty and the row still looks written. 0: put the printed URL in the cell, verbatim. 4: `QUESTION_{HASH}` is not on the wiki yet, so the record-page write has not landed — write that page again, then ask for the URL once more. 5: the page carries no `html_url`, so report it and never assemble a URL by hand. 7: the key is invalid or has no permission, so stop without retrying. 8: any other API failure, so retry once, then stop. Any other non-zero exit stops the same way. Whenever no URL comes back, write no row at all — an empty or hand-made cell is worse than a missing one — stop, report the exit code, and state that this repository's row was not indexed this round.
- Verify before writing: hand that URL, and every other link the row carries, to `jsc-gitea/tools/link-check.sh`, and branch on its exit code. 0: the links answer, so run the upsert. 1: at least one link is DEAD, so write no row and report the DEAD lines; `QUESTION_{HASH}` counts as written and unindexed, and this round's answers still go back to the calling skill. 2: no URL reached the script, so pass the links again. 3: `GITEA_HOST` is unset, so report that it must be set and run the check again; never upsert a row whose link skipped the check. 7: the Gitea key failed, so stop and report the key problem — a failed key makes live pages look dead, and an unchecked row would carry the blame instead. Done when the check exited 0 and the upsert ran, or no row was written and the report names the failing links or the exit code.
- Branch on `wiki-contents.sh`'s exit code, every code its own branch. 0: the row was added or updated, so this round is recorded. 1: the write failed, so retry once per step 3. 2: usage error, so stop and report the arguments that were passed — the same call retried fails the same way. A template path that does not exist lands here too, and means the plugin installation is incomplete. 3: no `CONTENTS` repo is configured, so report that `JSC_WIKI_REPO_CONTENTS` (or `JSC_WIKI_REPO`) must be set, note `QUESTION_{HASH}` as written but unindexed, and hand this round's answers back to the calling skill all the same. **Never withhold the answers over this code.**`JSC_WIKI_REPO_CONTENTS` is a `fix=ask` item in `jsc-cli/tools/config-spec.tsv`, so `/jsc-cli:setup` can only learn its value by asking through this skill; an answer dropped here leaves the variable unset, and the unset variable makes the next round drop the answer again. 4: the page does not exist and no template reached the script. The call form above always passes the template as the fifth argument, so this code cannot come out of it — getting it means that argument was dropped, so restore it and run the same call once more. 7: the key is invalid or has no permission, so stop and report without retrying. 8: any other API failure, so retry once per step 3, then stop and report.
- Done when the sub agent has reported both writes as succeeded and the main agent has accepted that one report — this single confirmation covers both pages and both templates; do not re-read the pages to prove it. Exit 2, 3 or 7 from `wiki-contents.sh`, any `wiki-url` failure, and any non-zero `link-check.sh` exit on the directory row, close this step the second way: `QUESTION_{HASH}` counts as written and unindexed, the report names the exit code and the page that stayed unwritten, and this round's answers go back to the calling skill regardless. **The answers of a finished questioning round are never lost because the directory page could not be written.**
-`QUESTION_CONTENTS` is a list page: one H2 block per repository, the block's fields written one per line as `- {欄位名}:{值}` in the order 存取庫名稱、問詢紀錄、最後更新. It is written by one call to `jsc-gitea/tools/wiki-contents.sh upsert QUESTION 2 QUESTION_{HASH} {block-file} templates/question-contents.md`. `key` is the H2 heading text, which is this repository's record page name `QUESTION_{HASH}` — the script matches the heading text after trimming, so pass it exactly as the block file writes it, with no link, no URL and no affix. The key is the page name and nothing else, because the page name follows from `{owner}/{repo}` alone: renaming the host, pointing `JSC_WIKI_REPO_QUESTION` at another repository, or a change in Gitea's page-name encoding all leave it untouched, so the key still finds the existing block. `key-col` is `2`, and it is not a free choice: it is the 1-based index of the column that held the link to the content page in the legacy markdown table, which for `QUESTION_CONTENTS` is the second column, 問詢紀錄. The script reads it only while converting such a legacy table page, and it takes the H2 heading of each converted block from that column's link. Passing `1` there names the 存取庫名稱 column, whose plain `{owner}/{repo}` text becomes a heading like `## plugins/meta`, which never matches the key `QUESTION_{HASH}`; the existing record is then appended as a new block, the page carries the same repository twice, and the old block can never be updated again. The block file holds this repository's whole H2 block: the `## QUESTION_{HASH}` line, a blank line, then the three field lines. The 存取庫名稱 field keeps the bare `{owner}/{repo}` text, and the 問詢紀錄 field is written as `[QUESTION_{HASH}]({url})`, where `{url}` is the absolute URL printed by `jsc-gitea/tools/gitea.sh wiki-url {question-repo} QUESTION_{HASH}`. Take that URL from the command only; never assemble a path by hand. The two pages sit in different repositories — the directory page in the `CONTENTS` repo, the record page in the `QUESTION` repo — so only an absolute URL crosses from one to the other. Always pass the template argument. The script owns the read-merge-write of that shared directory: it upserts this one block and touches no other repository's block, so do not read the page and rebuild it by hand.
- Branch on `wiki-url`'s exit code before the block is built, because a URL that never arrived leaves that field silently empty and the block still looks written. 0: put the printed URL in the 問詢紀錄 field, verbatim. 4: `QUESTION_{HASH}` is not on the wiki yet, so the record-page write has not landed — write that page again, then ask for the URL once more. 5: the page carries no `html_url`, so report it and never assemble a URL by hand. 7: the key is invalid or has no permission, so stop without retrying. 8: any other API failure, so retry once, then stop. Any other non-zero exit stops the same way. Whenever no URL comes back, write no block at all — an empty or hand-made field is worse than a missing one — stop, report the exit code, and state that this repository's block was not indexed this round.
- Verify before writing: hand that URL, and every other link the block carries, to `jsc-gitea/tools/link-check.sh`, and branch on its exit code. 0: the links answer, so run the upsert. 1: at least one link is DEAD, so write no block and report the DEAD lines; `QUESTION_{HASH}` counts as written and unindexed, and this round's answers still go back to the calling skill. 2: no URL reached the script, so pass the links again. 3: `GITEA_HOST` is unset, so report that it must be set and run the check again; never upsert a block whose link skipped the check. 7: the Gitea key failed, so stop and report the key problem — a failed key makes live pages look dead, and an unchecked block would carry the blame instead. Done when the check exited 0 and the upsert ran, or no block was written and the report names the failing links or the exit code.
- Branch on `wiki-contents.sh`'s exit code, every code its own branch. 0: the block was added or updated, so this round is recorded. 1: the page content could not be built or the write failed, so retry once per step 3 — a page with no block for this repository is not an error, it just means the block is appended. 2: usage error, so stop and report the arguments that were passed — the same call retried fails the same way. A template path that does not exist lands here too, and means the plugin installation is incomplete. 3: no `CONTENTS` repo is configured, so report that `JSC_WIKI_REPO_CONTENTS` (or `JSC_WIKI_REPO`) must be set, note `QUESTION_{HASH}` as written but unindexed, and hand this round's answers back to the calling skill all the same. **Never withhold the answers over this code.**`JSC_WIKI_REPO_CONTENTS` is a `fix=ask` item in `jsc-cli/tools/config-spec.tsv`, so `/jsc-cli:setup` can only learn its value by asking through this skill; an answer dropped here leaves the variable unset, and the unset variable makes the next round drop the answer again. 4: the page does not exist and no template reached the script. The call form above always passes the template as the fifth argument, so this code cannot come out of it — getting it means that argument was dropped, so restore it and run the same call once more. 7: the key is invalid or has no permission, so stop and report without retrying. 8: any other API failure, so retry once per step 3, then stop and report.
- Done when the sub agent has reported both writes as succeeded and the main agent has accepted that one report — this single confirmation covers both pages and both templates; do not re-read the pages to prove it. Exit 2, 3 or 7 from `wiki-contents.sh`, any `wiki-url` failure, and any non-zero `link-check.sh` exit on the directory block, close this step the second way: `QUESTION_{HASH}` counts as written and unindexed, the report names the exit code and the page that stayed unwritten, and this round's answers go back to the calling skill regardless. **The answers of a finished questioning round are never lost because the directory page could not be written.**
3. On a reported write failure, retry that one page once — a `QUESTION_{HASH}` failure, or `wiki-contents.sh` exit 1 or 8. Exit 2, 3 and 7 are not retried, because the same call fails identically until someone fixes the arguments, the environment or the key; they end the recording, not the round. Every one of these paths ends the same way: the answers go back to the calling skill, and the report names the page that stayed unwritten, the exit code behind it, and what was recorded and what was not. Done when the retry succeeded and step 3 of "Session cache" refreshed that page's copy, or — when the retry also failed, or the code was 2, 3 or 7 — the report above has been printed and the answers have been handed back.
4. Record how this run ended. This is the closing step and it runs on every route above, the ones that stopped early included. Run `jsc-hooks/tools/report-status.sh skill-end jsc-ask:ask {status} {exit} "{detail}"`, resolving the script the same sibling-plugin way this skill already resolves `jsc-gitea/tools/hash-id`. The hook that records a skill's start cannot see how it ended — it fires when the skill is loaded, and the work happens in later turns — so a start with no matching end is exactly what an abandoned run looks like, and writing this line is what keeps a finished run from reading as one.
-`{status}` is one of five. `ok`: every question of this round carries an answer, the answers went back to the calling skill, and where `{owner}/{repo}` was known both wiki pages were written. `degraded`: the round finished and part of the recording did not — no `{owner}/{repo}` was known so nothing was recorded at all, or `QUESTION_{HASH}` landed while `QUESTION_CONTENTS` did not (`wiki-contents.sh` exit 2, 3 or 7, any `wiki-url` failure, or a non-zero `link-check.sh` on the directory row). Those stay `degraded` rather than `failed` because the answers still reached the caller, which is this skill's own completion condition. `aborted`: the user stopped the questioning round, so the undecided points were never put to them. `failed`: the run stopped and no answers came back — `hash-id` found no SHA-1 helper, a wiki read failed with anything other than exit 4, or the one retry of a page write failed as well. `blocked` does not arise here, because anything that gates this skill stops it before it ever reaches this step.
-`{status}` is one of five. `ok`: every question of this round carries an answer, the answers went back to the calling skill, and where `{owner}/{repo}` was known both wiki pages were written. `degraded`: the round finished and part of the recording did not — no `{owner}/{repo}` was known so nothing was recorded at all, or `QUESTION_{HASH}` landed while `QUESTION_CONTENTS` did not (`wiki-contents.sh` exit 2, 3 or 7, any `wiki-url` failure, or a non-zero `link-check.sh` on the directory block). Those stay `degraded` rather than `failed` because the answers still reached the caller, which is this skill's own completion condition. `aborted`: the user stopped the questioning round, so the undecided points were never put to them. `failed`: the run stopped and no answers came back — `hash-id` found no SHA-1 helper, a wiki read failed with anything other than exit 4, or the one retry of a page write failed as well. `blocked` does not arise here, because anything that gates this skill stops it before it ever reaches this step.
-`{exit}` is the exit code of the tool that decided the outcome where one did, and otherwise 0 for `ok` and 1 for every other status. `{detail}` is optional, one line, at most 200 characters: name the page that stayed unwritten, or the tool and the code that stopped the run. Anything longer belongs in the report to the caller, not on this line.
- Reporting never changes the outcome of the round. `report-status.sh` is not on every machine, so a missing file is skipped in silence and nothing else about the run changes; the script swallows its own write failures and always exits 0, so its result is never worth branching on. Done when the call was made, or the script was absent and this step was skipped without a word.
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.