教訓目錄頁的版面從 markdown 表格換成「大標題加條列」:一個存取庫一個大標題 區塊,標題就是那個存取庫教訓頁的實際頁名,存取庫名稱、教訓紀錄連結、最後 更新時間改成標題底下的一層條列。範本與 learn 技能的寫入敘述一起跟上。 表格的欄位組合是整頁共用的,一頁上卻有很多存取庫各自的紀錄,每一輪只重寫 自己那一列。欄位一增減,舊列的格數與表頭就對不上,而目錄頁不能整頁覆蓋—— 覆蓋等於刪掉別人的紀錄。條列一筆一個區塊,欄位各自獨立,加一條只動到自己 那一個區塊。 比對鍵從存取庫名稱那一格改成大標題本身,標題寫成教訓頁的實際頁名。頁名只由 存取庫的擁有者與名稱決定,換主機位址、改存取庫或頁名編碼有差都動不到它。 欄號那個參數配合線上實際欄位改成教訓紀錄那一欄:轉檔時取那一格的文字當 標題,格子寫成連結就只取顯示文字。欄號填錯的話,轉出來的標題跟鍵對不上, 既有那一筆會被當成新的附加上去,同一個存取庫變兩個區塊。 範圍是教訓紀錄的目錄頁與 learn 技能。
13 KiB
name, description
| name | description |
|---|---|
| learn | Record a lesson learned after a skill run to wiki LEARN_{HASH} plus LEARN_CONTENTS, or consult past lessons before a skill run. Each entry is one table row with date, skill, CLI, situation, lesson, and next-time approach. HASH is the full 40-character uppercase SHA-1 of {owner}/{repo}; LEARN_{HASH} sits in the LEARN wiki repo while LEARN_CONTENTS sits in the separate CONTENTS repo, so the directory entry goes through jsc-gitea/tools/wiki-contents.sh upsert as one H2 block keyed by the page name LEARN_{HASH}, with a bullet per field and the lesson page linked by its absolute wiki-url. Use when a skill run produced a reusable lesson, or before running a skill to consult past lessons; not for work-time logs (see worklog). |
learn — lessons learned
Close the loop on skill runs: record what a run taught you, consult it before the next run. Two modes — record and consult. Page content is chart-first Traditional Chinese (STE100): markdown table entries, prose as the last resort.
Target pages
- Directory page:
LEARN_CONTENTS. Content page:LEARN_{HASH}, one page per repository. - The two pages live in different wikis.
LEARN_{HASH}goes tojsc-gitea/tools/gitea.sh wiki-repo LEARN;LEARN_CONTENTSgoes togitea.sh wiki-repo CONTENTS(JSC_WIKI_REPO_CONTENTS, thenJSC_WIKI_REPO, then exit 3), which never falls back to the LEARN repo. Exit 3 on either hands the question tojsc-gitea:wiki, which owns the resolution order and the wording; exit 2 means the type argument was misspelled, so fix it and rerun. - Every link this skill writes takes the shape
[{text}]({absolute URL}). The directory block's 教訓紀錄 bullet links the lesson page as[LEARN_{HASH}](<url>), with<url>fromgitea.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-urlexit 4 means the lesson page is not written yet, so write it first; exit 5 means the page carries nohtml_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}withjsc-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 thatsha1sumorshasumhas 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 theLEARN_CONTENTSblock, which goes throughjsc-gitea/tools/wiki-contents.sh. - The two pages carry different shapes.
LEARN_{HASH}stays a markdown table, one row per lesson.LEARN_CONTENTSis a list page:# 教訓目錄, a>preamble, then one H2 block per repository whose heading is that repository's lesson page name.
Mode: record
Run after a skill run that produced a reusable lesson.
-
Collect the six facts below. Done when every field has a value.
# Field (page column) Source 1 日期 Today, yyyy-MM-dd2 技能 The skill that ran, as jsc-{domain}:{name}3 CLI One of claude / codex / copilot / antigravity / kiro 4 情境 What was happening when the lesson appeared, one sentence 5 教訓 What the run taught, one sentence 6 下次做法 How to apply it on the next run, one sentence -
Resolve
{owner}/{repo}fromgit remote get-url originand compute{HASH}withjsc-gitea/tools/hash-id. Done when the page nameLEARN_{HASH}is known. -
Write the entry. This step MUST run as a sub agent; the main agent only confirms the write succeeded.
-
Read
LEARN_{HASH}viajsc-gitea:wikiand branch on the exit code the underlyinggitea.sh wiki-getreturned. Only exit 4 means the page is not there yet; creating the page from the template on any other code appends this one row to a blank table and drops every lesson already recorded.Exit Do 0 The table is in hand. APPEND the new row at the end of it and overwrite no existing row. Never rebuild the page from the template on this code 4 The page really is absent. Create it from templates/learn-page.md, then add the row7 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-urloutput tojsc-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 and the directory block 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_HOSTis unset. Set it and rerun; never skip the check7 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_CONTENTSin the same pass, and letjsc-gitea/tools/wiki-contents.shdo the block work — never hand-edit the directory page. Build one file holding the single H2 block fromtemplates/learn-contents.md— the## LEARN_{HASH}heading, a blank line, then one- {欄位名}:{值}bullet per field in the template's order: the repository name, the absolute link fromgitea.sh wiki-url <LEARN repo> LEARN_{HASH}, and the update time. Then run:jsc-gitea/tools/wiki-contents.sh upsert LEARN 2 "LEARN_{HASH}" {block file} templates/learn-contents.mdThe key is the H2 heading itself, the content page name
LEARN_{HASH}, so it stays the same string across every run and one repository keeps exactly one block. The 教訓紀錄 bullet carries that same page as a link, and that link is what must not be the key: it embeds the host and the encoded page name, so one change ofGITEA_HOST, one move ofJSC_WIKI_REPO_LEARN, or one difference in how Gitea encodes the page name makes the match fail and appends a second block for the same repository. The page name depends only on{owner}/{repo}. The2is<key-col>, which the script uses only while the directory page is still an old markdown table — it names the column whose cell text (the link text alone) becomes the H2 heading, and a page already in list shape ignores it. The script reads the whole page, replaces the matching block and appends when none matches, so every block that belongs to another repository stays as it was.Exit Do 0 The block is in place. It prints updatedoraddedplus the page it wrote1 The page content could not be assembled, or the write failed. Report LEARN_CONTENTSas not written, together with the block content. A page with no matching block is not this code: the block is appended instead2 An argument was rejected. Fix the argument and rerun this bullet; nothing was written 3 No CONTENTS wiki repo is configured. Report JSC_WIKI_REPO_CONTENTSandJSC_WIKI_REPOas the two variables to set. The lesson itself is onLEARN_{HASH}and stays there4 The directory page is absent and the script received no template. The call above always passes one, so this code means templates/learn-contents.mdis not at that path — a partial plugin install, not a missing argument. Stop and report the path; rerunning the same command changes nothing. Reinstall the plugin, confirm the file is there, then rerun. A mistyped template path exits 2, not 47 The token is invalid or lacks permission, so the other repositories' blocks are unknown. Stop and report the token problem; the script wrote nothing, which is what keeps those blocks alive 8 Some other API failure. Stop and report that status and retry only after the API is back -
A failed write on either page: retry once. Still failing, stop and report which page was not written (
LEARN_{HASH}orLEARN_CONTENTS) together with the row or block content that was meant to go in, so the lesson is not lost. Never report a page as written when it was not. -
Done when the sub agent reports both pages written, the main agent has confirmed the row exists on
LEARN_{HASH}and the block onLEARN_CONTENTS, and every row and block that was there before is still there.
-
Mode: consult
Run before a skill run, to apply past lessons.
-
Resolve
{owner}/{repo}and compute{HASH}as in record mode. Done whenLEARN_{HASH}is known. -
Read
LEARN_CONTENTSfrom the CONTENTS repo and the repo'sLEARN_{HASH}from the LEARN repo viajsc-gitea:wiki— twowiki-repocalls, two different wikis — and branch on the exit codejsc-gitea/tools/gitea.shreturned. Only 4 means the page is absent; every other failure code means the read never happened, so an empty page must never be inferred from it. The blocks onLEARN_CONTENTSpoint at lesson pages by absolute URL, and blocks for other repositories point outside the LEARN repo resolved here, so follow each link as given rather than treating the H2 heading as a page in this wiki.Exit Do 4 The page does not exist. Report 「無教訓紀錄」 for that page and let the caller proceed 5 The page carries no html_url. Stop and report it; never assemble the URL by hand and never read it as an empty page7 The Gitea token is invalid or lacks permission (HTTP 401/403). Stop and report that the token has to be fixed. Reading this as 「無教訓紀錄」 is exactly the misread gitea.shseparates 7 from 4 to prevent8 Some other API failure, with the HTTP status in the message. Stop and report that status; retry only after the API is back Done when both pages are read, or reported missing under exit 4, or the run stopped on 5, 7 or 8.
-
Surface every row whose 技能 matches the skill about to run, and summarize each matched 下次做法 for the caller to apply. Done when the matched rows (or 「無相符教訓」) are reported.
Close: record how the run ended
Both modes end here, as the very last thing this skill does:
jsc-hooks/tools/report-status.sh skill-end jsc-log:learn {status} {exit} "{detail}"
Resolve that path the way this file already resolves jsc-gitea/tools/hash-id and the other sibling plugin scripts — the sibling plugin directory, no separate lookup rule for this one call. A missing script is not a failure here: skip this step in silence and let the run end as it stands. The script swallows its own write errors and exits 0 even then, so nothing branches on its code either. A lesson that was recorded stays recorded whether or not the recorder of recorders was installed.
| status | This skill's case |
|---|---|
ok |
record — LEARN_{HASH} carries the new row and LEARN_CONTENTS this repository's block, and everything that was there before is still there. consult — both pages were read, or a page was reported absent under exit 4, and the matched 下次做法 lines reached the caller |
blocked |
The run never reached a page: hash-id exit 1 (no SHA-1 helper), wiki-repo LEARN or wiki-repo CONTENTS exit 3 (no wiki repo configured for that page type), or link-check.sh exit 3 (GITEA_HOST unset) |
degraded |
record — the lesson row is on LEARN_{HASH} but wiki-contents.sh upsert did not land the directory block (exit 1, 3, 7 or 8), so the lesson is on the wiki and nothing points at it. consult — one of the two pages was read and the other stopped the run, so the caller got part of the lesson set and knows it |
failed |
An API call answered with something unexpected after the work started: link-check.sh exit 1 on a DEAD link, a wiki-get that came back 7 or 8, or a page write that failed its retry as well. Nothing reached LEARN_{HASH} |
aborted |
The user stopped the run, or record mode was called with nothing reusable to record, so the six facts never formed an entry and no write was attempted |
{exit} is the exit code of whatever decided the status, 0 for ok. {detail} is one short line well under 200 characters: the mode plus counts and exit codes, never the lesson text, page names, branch names, or personal data.
Done when the command has run, or the script was absent and this step was skipped.