feat(link): 連結一律寫成 [文字](絕對網址),寫入前先驗證連得到
取消 [[頁名]] 與 [[顯示文字|頁名]] 兩種同 wiki 寫法,不再分「同存取庫」與 「跨存取庫」兩條規則。那種寫法只在自己那個 wiki 內解析,寫錯不報錯,畫面上 看起來像普通文字或死連結,巡不到也修不了。 連結寫進頁面前先過 jsc-gitea 的 link-check.sh,結束碼 0 才寫。驗證一律走 API, 不看網頁狀態碼:私有存取庫的網頁網址對未登入請求一律回 404,拿狀態碼判會把 好連結判成壞的。認證失敗回 7,與死連結的 1 分開,免得金鑰一過期就把還在的頁 整批判死。
This commit is contained in:
+20
-8
@@ -10,7 +10,7 @@ This skill is a **logic-only** stage: never output code, and **never modify any
|
||||
|
||||
`{HASH}` = the shared wiki hash for `{owner}/{repo}`, computed by `jsc-gitea/tools/hash-id` (see `jsc-gitea:wiki`). It prints the **full 40-character uppercase SHA-1** of its input — no truncation to 8 characters, no prefix rewrite. Never shorten it by hand: a shortened name points at a page nobody else writes to. `REPO_{HASH}` runs the same command over that repository's own `{owner}/{repo}`, so a multi-repository analysis holds one inventory page per repository.
|
||||
|
||||
**Content pages and directory pages live in different wiki repos.** `ANALYZE_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo ANALYZE` resolves, `REPO_{HASH}` in the one `gitea.sh wiki-repo REPO` resolves. All three directory pages — `ANALYZE_CONTENTS`, `PLAN_CONTENTS` and `REPO_CONTENTS` — sit in the repo `gitea.sh wiki-repo CONTENTS` resolves: `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to `JSC_WIKI_REPO_ANALYZE`, `JSC_WIKI_REPO_PLAN` or `JSC_WIKI_REPO_REPO`. Because directory and content pages sit in different wikis, every directory row links its content page by the absolute URL from `gitea.sh wiki-url {content repo} {page}`; `[[...]]` resolves only inside one wiki and would dead-link from the directory.
|
||||
**Content pages and directory pages live in different wiki repos.** `ANALYZE_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo ANALYZE` resolves, `REPO_{HASH}` in the one `gitea.sh wiki-repo REPO` resolves. All three directory pages — `ANALYZE_CONTENTS`, `PLAN_CONTENTS` and `REPO_CONTENTS` — sit in the repo `gitea.sh wiki-repo CONTENTS` resolves: `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to `JSC_WIKI_REPO_ANALYZE`, `JSC_WIKI_REPO_PLAN` or `JSC_WIKI_REPO_REPO`. Every directory row links its content page by the absolute URL from `gitea.sh wiki-url {content repo} {page}`, written as `[{text}]({url})` — one link syntax, whichever wiki the two pages sit in. The syntax and the check that runs before every write: "Every link is checked before it reaches a page" below.
|
||||
|
||||
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Step 11 still runs after such a stop.
|
||||
|
||||
@@ -28,7 +28,7 @@ All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or w
|
||||
1. Every file in the working directory, at the commit `origin/{source-branch}` points to (verified in step 4).
|
||||
2. **Reuse an existing method or endpoint unless its logic cannot satisfy the requirement**:
|
||||
- Check the `REPO_{HASH}` inventory page first, in the REPO wiki repo. **Its `{HASH}` is `hash-id` over that repository's own `{owner}/{repo}`** — one inventory page per repository, so a multi-repository analysis holds one `REPO_{HASH}` per repository and never one shared page. Re-inventory when the feature or endpoint is missing, or when the recorded commit sha differs from the current one.
|
||||
- Re-inventory **MUST run as a sub agent**: analyze the repository's features and endpoints, attach the current commit sha, write back to `REPO_{HASH}` with `templates/repo-page.md`, then upsert this repository's row in `REPO_CONTENTS` with `jsc-gitea/tools/wiki-contents.sh upsert REPO 1 {owner}/{repo} {row file} templates/repo-contents.md`. The row follows `templates/repo-contents.md`, and the key is column 1, the repository name, written exactly as the row file writes it. Its 盤點頁 cell holds the absolute URL from `gitea.sh wiki-url {REPO repo} REPO_{HASH}` — take that URL first and branch on the exit code per "Every cross-repo link comes from `wiki-url`" below, because the row must never carry an empty link cell.
|
||||
- Re-inventory **MUST run as a sub agent**: analyze the repository's features and endpoints, attach the current commit sha, write back to `REPO_{HASH}` with `templates/repo-page.md`, then upsert this repository's row in `REPO_CONTENTS` with `jsc-gitea/tools/wiki-contents.sh upsert REPO 1 {owner}/{repo} {row file} templates/repo-contents.md`. The row follows `templates/repo-contents.md`, and the key is column 1, the repository name, written exactly as the row file writes it. Its 盤點頁 cell holds the absolute URL from `gitea.sh wiki-url {REPO repo} REPO_{HASH}`, written as `[{text}]({url})` — take that URL first, check it with `jsc-gitea/tools/link-check.sh`, and branch on both exit codes per "Every link comes from `wiki-url`, and is checked before it is written" below, because the row must never carry an empty or dead link cell.
|
||||
- Never hand-edit `REPO_CONTENTS`, and never touch a row belonging to another repository. Branch on the script's exit code — see "Contents pages are appended, never overwritten" below. `REPO_{HASH}` is a content page for one repository, so rewriting it whole is correct; the directory page around it is not.
|
||||
- For each reuse candidate, confirm the file path and method name first, then analyze whether its logic fits the requirement. Reject a candidate only for a stated reason, and record both the candidate and that reason in the analysis page's 複用決策 field.
|
||||
|
||||
@@ -41,11 +41,11 @@ All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or w
|
||||
2. Every scenario states its input, its expected result, its data source and the work package it belongs to.
|
||||
3. **Every TDD todo is one whole cycle**: one seam, one failing test first, one minimal implementation, one green verification, and a post-green refactor where it is needed. Never split the red test, the minimal implementation and the green verification into separate todos. Seams and anti-patterns: `references/tdd.md`.
|
||||
4. Completion condition: every user story has scenarios under `## 使用者故事驗收計畫`; every scenario carries an explicit acceptance method and data source; the scenario count matches the story's complexity; every work package has its own subsection under `## 測試計畫(TDD)`; every implementation work package holds at least one test-first `[ ]` todo; and every todo states its seam, its acceptance scenario, the behaviour the test asserts, the minimal implementation scope and how green is verified. A pure delivery package may use document-verification or sample-data-verification todos instead, and still states the test evidence or the review evidence that proves the spec is usable.
|
||||
10. **Write the analysis page and its catalogue entries in one wiki pass.** Apply `templates/analyze-page.md` to create or update the analysis page **in the ANALYZE wiki repo** and write it back via `jsc-gitea:wiki`; the page content is Traditional Chinese, exactly as the template dictates. Both directory rows then go through `jsc-gitea/tools/wiki-contents.sh`, never a hand-edited page:
|
||||
- `jsc-gitea/tools/wiki-contents.sh upsert ANALYZE 3 {HASH} {row file} templates/analyze-contents.md` — the row follows `templates/analyze-contents.md` and the key is the HASH column, column 3. Its 分析頁 cell holds the absolute URL from `gitea.sh wiki-url {ANALYZE repo} ANALYZE_{HASH}`: take that URL after the analysis page is saved and branch on the exit code per "Every cross-repo link comes from `wiki-url`" below, because the row must never carry an empty link cell.
|
||||
10. **Write the analysis page and its catalogue entries in one wiki pass.** Apply `templates/analyze-page.md` to create or update the analysis page **in the ANALYZE wiki repo** and write it back via `jsc-gitea:wiki`; the page content is Traditional Chinese, exactly as the template dictates. **Every link the page carries — the plan page, the inventory page, issues, anything external — is written as `[{text}]({url})` and passes `jsc-gitea/tools/link-check.sh` before the write**, per "Every link comes from `wiki-url`, and is checked before it is written" below. Both directory rows then go through `jsc-gitea/tools/wiki-contents.sh`, never a hand-edited page:
|
||||
- `jsc-gitea/tools/wiki-contents.sh upsert ANALYZE 3 {HASH} {row file} templates/analyze-contents.md` — the row follows `templates/analyze-contents.md` and the key is the HASH column, column 3. Its 分析頁 cell holds the absolute URL from `gitea.sh wiki-url {ANALYZE repo} ANALYZE_{HASH}`, written as `[{text}]({url})`: take that URL after the analysis page is saved, check it with `jsc-gitea/tools/link-check.sh`, and branch on both exit codes per "Every link comes from `wiki-url`, and is checked before it is written" below, because the row must never carry an empty or dead link cell.
|
||||
- `jsc-gitea/tools/wiki-contents.sh upsert PLAN 4 {HASH} {row file} templates/plan-contents.md` — rebuild that plan's row from the one the page already holds, change only its status to the literal 「已分析」, and keep every other cell (including the absolute plan-page link) byte-for-byte as it was. The key is the HASH column, column 4.
|
||||
|
||||
Both runs branch on the exit code per "Contents pages are appended, never overwritten" below. Completion condition: the analysis page is saved on the wiki carrying every section the template dictates — the source branch, the head sha and the 未決項 section (「無」 when there is none) included — every `wiki-url` call this step made returned 0 and its URL is the one in the row, both `wiki-contents.sh` runs exited 0, and `ANALYZE_CONTENTS` shows this analysis's row while `PLAN_CONTENTS` shows the literal 「已分析」.
|
||||
Both runs branch on the exit code per "Contents pages are appended, never overwritten" below. Completion condition: the analysis page is saved on the wiki carrying every section the template dictates — the source branch, the head sha and the 未決項 section (「無」 when there is none) included — every `wiki-url` call this step made returned 0 and its URL is the one in the row, every link written by this step was cleared by a `link-check.sh` run that exited 0, both `wiki-contents.sh` runs exited 0, and `ANALYZE_CONTENTS` shows this analysis's row while `PLAN_CONTENTS` shows the literal 「已分析」.
|
||||
11. **Stage report — the last thing this stage does, including every early stop** (the model gate blocked, the working tree did not match `origin/{source-branch}`, no plan was selectable, a wiki read or write failed). Run `tools/stage-report.sh analyze` with one `--page TYPE:{page}` per wiki page this run wrote — `--page ANALYZE:ANALYZE_{HASH}`, `--page CONTENTS:ANALYZE_CONTENTS`, `--page CONTENTS:PLAN_CONTENTS`, and `--page REPO:REPO_{HASH}` plus `--page CONTENTS:REPO_CONTENTS` when a re-inventory happened. **Every directory page takes the `CONTENTS` type**: the script resolves each page's repo from the TYPE you pass, and a directory page passed under its old type resolves the wrong repo and prints no URL. Add `--worklog` and `--worklog-heading` when a work log entry exists. No work log yet: write this stage's log content to a file — with a Bash heredoc or `mktemp` per Hard limits, never with `Write` or `Edit` — and pass `--pending-file {file} --log-hash {HASH}` so it is held for the next `jsc-log:worklog` run. Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and every wiki page this run wrote appears in it.
|
||||
|
||||
## Contents pages are appended, never overwritten
|
||||
@@ -68,9 +68,11 @@ Why 7 and 8 abort: both mean the old content is unknown, not that the page is mi
|
||||
|
||||
Completion condition: every directory-page write this stage made names the `wiki-contents.sh` exit code it branched on, and no directory page was created on any code other than 4.
|
||||
|
||||
## Every cross-repo link comes from `wiki-url`
|
||||
## Every link comes from `wiki-url`, and is checked before it is written
|
||||
|
||||
Both directory rows this stage writes — `REPO_CONTENTS` in step 5.2 and `ANALYZE_CONTENTS` in step 10 — link a content page that lives in another wiki repo, so the cell holds the absolute URL `gitea.sh wiki-url {content repo} {page}` printed and nothing else. Run it **after** that content page is saved, and branch on its exit code; this is the same branching `jsc-log:worklog` runs over the same call.
|
||||
**One syntax.** Every link this stage writes — on `ANALYZE_{HASH}` and `REPO_{HASH}`, in the `ANALYZE_CONTENTS`, `PLAN_CONTENTS` and `REPO_CONTENTS` rows, in the stage report — is written as `[{text}]({url})`. The `{url}` is the absolute URL `gitea.sh wiki-url {repo} {page}` printed, used verbatim: never assemble a wiki path by hand, and never write a link as `[[頁名]]` or `[[顯示文字|頁名]]`. That form resolves only inside the wiki it sits in, and it fails without an error — the reader sees plain text or a dead link, so a wrong link is neither noticed nor fixable.
|
||||
|
||||
Run `wiki-url` **after** the content page it names is saved, and branch on its exit code; this is the same branching `jsc-log:worklog` runs over the same call.
|
||||
|
||||
| Exit | What this step does |
|
||||
| --- | --- |
|
||||
@@ -82,7 +84,17 @@ Both directory rows this stage writes — `REPO_CONTENTS` in step 5.2 and `ANALY
|
||||
|
||||
Never let an empty string stand in for the URL. A row whose link cell is empty is a directory entry that points nowhere, the reader has no way to reach the page it names, and the next run replaces that row as if it were correct.
|
||||
|
||||
Completion condition: every row this stage upserted carries a URL that came out of a `wiki-url` run that exited 0, and every non-zero code was branched on as this table says.
|
||||
**Checked before it is written.** Collect every link the page or the row is about to carry, hand them all to `jsc-gitea/tools/link-check.sh` in one run — `link-check.sh {網址}...`, or the same URLs on stdin, one per line — and write only when that run exits 0. It prints one `{OK|DEAD|SKIP}<TAB>{網址}<TAB>{說明}` line per URL. The check goes through the API, never a web status code: a private repository's web URL answers 404 to a request carrying no key, so a status-code check marks live pages dead.
|
||||
|
||||
| Exit | What this step does |
|
||||
| --- | --- |
|
||||
| 0 | every link answers — write the page or upsert the row |
|
||||
| 1 | at least one link is dead — **write nothing**, and report the `DEAD` lines to the user |
|
||||
| 2 | usage error: not one URL was passed — pass the links and run it again |
|
||||
| 3 | the list holds a Gitea URL but `GITEA_HOST` is unset — report it as a setting to fix and run it again, and never skip the check instead |
|
||||
| 7 | Gitea authentication failed (401/403) — stop and report the key problem. Never read this as exit 1: an expired key makes live pages look absent, and a row rewritten on that reading loses the links that were fine |
|
||||
|
||||
Completion condition: every row this stage upserted carries a URL that came out of a `wiki-url` run that exited 0, every page and row this stage wrote was cleared by a `link-check.sh` run that exited 0, and every non-zero code from either script was branched on as these tables say.
|
||||
|
||||
## Delivery package is WP-01
|
||||
|
||||
|
||||
Reference in New Issue
Block a user