過去先問來源分支、先產生工作證、先建 worktree,等跑到閘門才發現沒有可挑的項目。前面的決策樹、wiki 寫入、抓取遠端與改名全部白做。 - 實作先讀分析頁、先結清已開 PR 的留言,再逐一過相依閘門,只有通過的候選才進選項。來源分支與工作證都移到領到工作包之後。 - 分析先併行讀計畫與分析目錄,沒有可分析的計畫就直接停。分支隨計畫而變,所以等目標定了才問。 - 互不相依的呼叫改成併發:已開 PR 的狀態批次預取、每個候選的相依查詢同時發、多個存取庫的 worktree 一起建、兩道收尾稽核並列跑。 - 領取登錄不成功就不得開工。沒有登錄,存取庫就沒有歸屬紀錄,之後每一支 PR 都會被當成無人認領而放行。上鎖失敗同樣要停,否則下一個工作階段會在 PR 還沒合併時就被放行。 - 來源分支改成單鍵確認。放棄的是每輪都要使用者明講「來源分支同時是 PR 目標」這道確認;分析頁沒記錄、遠端找不到分支這兩種例外仍走完整決策樹。 - 把仍寫成中文的驗收計畫步驟改回英文,與其他步驟一致。
114 lines
29 KiB
Markdown
114 lines
29 KiB
Markdown
---
|
|
name: implement
|
|
description: SDLC implementation stage. Gate on capability tags enforced in code by sdlc-gate (implement requires coding), settle every open work package's PR comments first, then claim a ready package before confirming the analysis page's source branch - it is both the worktree base and the PR target. Every already-open work package's PR comments get triaged via tools/wp-gate.sh check and fixed by sub agents only after jsc-ask consensus, never blocking an unrelated package; every candidate is gated in code by tools/wp-gate.sh check-deps before it reaches the options, and claiming records the package number via tools/wp-gate.sh claim so tools/wp-gate.sh owns keeps every session on its own package's PR. Claim a ready work package from ANALYZE_CONTENTS with a work ticket, confirm a delivery package's content type, then complete its TDD todos one at a time inside a worktree built from origin/{source-branch}, updating the wiki after every item, closing with the two side-by-side audits jsc-review code-review and jsc-review api-doc (the latter gated by swagger-detect.sh and explicitly skipped where the project has no Swagger support), one PR back to the source branch, a jsc-gitea pr-watch.sh poll that holds until that PR merges, a jsc-log:worklog entry per finished task, the chosen delivery document, an optional MAINTAIN_CONTENTS entry, and a tools/stage-report.sh report covering the model tag verdict, the worklog link, every wiki link written, the worktree and the three branches. Use when analysis is done and code must be written; not for planning or analysis.
|
|
---
|
|
|
|
# implement
|
|
|
|
Goal: complete the analysis page's todos one by one; **update the wiki status immediately after every completed item**.
|
|
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 13 still runs after such a stop.
|
|
|
|
## Steps
|
|
|
|
1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock implement`. This stage requires the `coding` capability tag. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the actual model id it read from the transcript, and the verdict.
|
|
2. **Read the analysis pages, then settle every already-open work-package PR's comments — this keeps existing PRs moving and can clear a dependency for step 4, but it does not by itself decide which new package may start (step 4 does)**:
|
|
1. Read `ANALYZE_CONTENTS`, then read every analysis page it lists as unfinished. **Keep this read: steps 3, 5 and 8 reuse it and never read the same pages again.** Completion condition: for every unfinished analysis page you hold its WBS table, its PR column, its source branch and the repositories it names.
|
|
2. **Prefetch every open PR's state in one batch.** For every work package holding a PR that is not marked merged, run `jsc-sdlc/tools/wp-gate.sh check {owner}/{repo} {index} --since {the comment timestamp recorded in that PR column}`. Drop `--since` when that package has no recorded timestamp yet. **These calls do not depend on each other — run them concurrently and collect every result before you ask the user anything.** The consensus rounds and the fixes that follow stay one comment at a time. Completion condition: every open PR has a recorded exit code and `status=` line.
|
|
3. Exit 0 (`status=merged`) clears that package: remove its worktree (`references/branch.md`) and mark the package done on the analysis page.
|
|
4. Exit 1 (`status=open` or `status=closed-unmerged`) means that package's own PR is not settled yet. **This does not block picking a different, unrelated work package** — SDLC implementation can run several independent packages in parallel; an unmerged PR only holds back packages that depend on it (step 4 checks that specifically), never the whole analysis page. Sub-steps 2.5 to 2.10 are the one comment round this skill owns; step 11.5 runs the same sub-steps for the PR it just opened.
|
|
5. **The PR has to be yours before you touch it.** Run `jsc-sdlc/tools/wp-gate.sh owns {owner}/{repo} {index} --wp {the work package number that PR column belongs to}`. `status=owned` (exit 0) → carry on. `status=foreign` (exit 1) → leave that PR alone, name the work package the script says holds it, and let that package's own session handle it. `status=unowned` (exit 0) → carry on, and report that ownership could not be determined. `status=usage` (exit 2) → bad arguments; fix them and run it again, and change nothing on that PR until the script returns a verdict. Completion condition: the script has run for that PR and its verdict is reported.
|
|
6. **Agree on the fix before making it.** Run the `jsc-ask:ask` decision tree over the comments the script printed — issue comments, review verdicts and inline comments alike — one option set per comment, each option stating its impact scope (which files it touches, whether it changes the package's TDD todos). **Never fix a comment automatically**: a reviewer's wording often allows two different fixes, and picking one silently costs another review round. Completion condition: the user has said how each comment is handled before any file is edited.
|
|
7. **Each round of fixes MUST run as a sub agent** inside that package's own worktree, pushing to the same work branch, so the PR updates itself. Hand the sub agent the agreed decisions and let the comment text stay inside it — the main agent keeps only the decisions and the bookkeeping. Never open a second PR for the same package.
|
|
8. Give every printed comment an outcome — fixed, no fix needed, or cannot fix. Reply to every handled comment with `jsc-gitea/tools/gitea.sh comment-reply {owner}/{repo} {index} {issue|review|inline} {comment id} {reply file}`. The reply states the outcome and the commit, file, or reason. Pure discussion and praise can be ignored only when you list the reason. Rules and the completion condition: `jsc-meta/references/pr-report.md`.
|
|
9. Write the script's `latest=` value into that work package's PR column, appended after the existing PR link as `#{index} 已處理留言 {ISO time}`, and save the page back to the wiki. Next run passes it as `--since`, so handled comments stay handled. Reuse the existing PR column and add no new column; the analysis page's columns belong to `analyze`.
|
|
10. **One round of comment fixes is one finished task — call `jsc-log:worklog` now**, under the Rules section's one-task-one-entry rule. **Resolve that package's PLAN and ANALYZE wiki repositories and page URLs once and hand the resolved values to every call**: the same package's later rounds reuse them, and only a change of repository forces a fresh resolution. Completion condition: the entry for this round is saved on `LOG_{HASH}` before the next round starts.
|
|
11. Exit 2 (`status=usage`) means bad arguments — a malformed `{owner}/{repo}`, a missing index, or a `--since` value that is not the previous round's `latest=`. Fix the arguments and run it again. Completion condition: the rerun returned 0, 1 or 3; a usage error never counts as merged, settled or blocked.
|
|
12. Exit 3 (`status=missing-dep`) means the gate could not decide (a missing dependency script, or the PR could not be found). Report it and stop — an undecidable gate never counts as merged.
|
|
13. Completion condition: every work package holding an unmerged PR has had this run's comments triaged (fixed, no fix needed, or cannot fix), logged and reported; a package left unmerged after this does not block steps 3 and 4 for packages that do not depend on it.
|
|
3. From the pages read in step 2.1, list what is unfinished: plan name, HASH, work package number, count of open items. A selectable work package satisfies both: **unfinished, and not holding a work ticket**. Dependencies are not judged here and never by eyeballing the 相依 column — step 4's `wp-gate.sh check-deps` is the only judge. Completion condition: you have listed every selectable work package, or reported that none is selectable and stopped.
|
|
4. **Every candidate passes the dependency gate before the user sees it — the gate lives in code, not in this text, and it judges one candidate at a time, never every open PR on the page**:
|
|
1. Run `jsc-sdlc/tools/wp-gate.sh check-deps {owner}/{repo} {wp-number} --analyze ANALYZE_{HASH}` **once per candidate from step 3, before asking the user anything**. Candidates do not depend on each other's verdict, so run these concurrently. The script re-reads the caller-specified analysis page and queries Gitea itself — it does not trust anything you already read or concluded, and it never guesses the page from the repository hash.
|
|
2. Branch on each candidate's exit code. Exit 0 (`status=ready`) → put it in the option list. Exit 1 (`status=blocked`) → keep it out of the option list, and report which dependency work package's PR is not merged yet. Exit 3 (`status=missing-dep`) is an undecidable gate — report it and stop; never treat an undecidable result as either ready or blocked. Exit 2 (`status=usage`) → bad arguments or a missing `--analyze`; fix them and run that candidate again, and leave it out of the options until the rerun returns a verdict. Completion condition: every candidate from step 3 carries one of these verdicts, and only the `ready` ones remain.
|
|
3. A dependency phrased as text pointing outside this analysis page (another plan, another analysis) cannot be checked by the script; it comes back listed separately as needing manual confirmation. Confirm it with the user before proceeding — an unchecked cross-page dependency is not the same as a cleared one.
|
|
4. Let the user pick per `jsc-ask:ask` rules from the `ready` candidates only (options state open-item count and estimated effort). **List delivery packages (交付 `是`) first** — the analysis page makes `WP-01` the standalone delivery package, so keep that order in the options. Completion condition: the user has named one `ready` work package, and any cross-page dependency of it is confirmed.
|
|
5. **Record the claim in code, so later steps can tell this package's PR from any other package's**: run `jsc-sdlc/tools/wp-gate.sh claim {owner}/{repo} {wp-number} --analyze ANALYZE_{HASH}`, with the number read off the analysis page — the work package number is the only thing ownership is judged by (`references/branch.md`). One repository holds one claim at a time; `wp-gate.sh check` hands it back once the PR merges. Branch on the exit code: exit 0 (`status=claimed`) → proceed. Exit 2 (`status=usage`) → fix the arguments and run it again. Exit 3 (`status=missing-dep`) → the claim could not be recorded; report it and stop. **No recorded claim, no work**: without it the repository has no owner on record, `owns` answers `unowned` for every PR from then on, and every later session is waved through onto this package's PR. Completion condition: `claim` returned `status=claimed`; only then may you proceed.
|
|
5. **Confirm the source branch — it is also this stage's PR target**:
|
|
1. Run `git fetch --prune origin`, then take the source branch from the analysis page already read in step 2.1 and report it, along with the current branch and whether the working tree is clean.
|
|
2. **Show the recorded value and take a single-key confirmation.** The analysis page already carries the answer, so this is a confirmation, not a fresh question: print `origin/{source-branch}` as both the worktree base and the PR target for this work package, and accept one key to confirm it. Two cases have no shortcut and go through the full `jsc-ask:ask` decision tree, each option stating its impact scope: **the analysis page records no source branch**, and **`origin/{source-branch}` does not exist on the remote**.
|
|
3. **A source branch missing from the remote is a stop-and-report condition, never a silent fallback.** That rule (section 「來源分支在遠端找不到」), the remote-only basis and the uncommitted-changes rules: `references/branch.md`.
|
|
4. Completion condition: the user has confirmed the source branch — by the single key, or through the decision tree in either exception case — and it is recorded in the analysis page's 「來源分支」 column.
|
|
6. **Generate a work ticket and claim the package on the page**: format `TICKET_{yyyyMMdd}_{HHmmss}_{HASH}`. `{HASH}` = the shared wiki hash for `{owner}/{repo}`, computed by `jsc-gitea/tools/hash-id` (see `jsc-gitea:wiki`). Rename the current session to the ticket name; skip the rename only when the CLI exposes no rename command. Write the ticket into the picked work package's ticket column (the zh-TW field 「工作證」) on the analysis page and save it back to the wiki. Completion condition: the ticket string exists, it is saved in that package's 「工作證」 column on the wiki, and you have reported it together with which branch applied — renamed, or skipped because this CLI has no rename command.
|
|
7. **A delivery/handover package confirms its content before its first todo**:
|
|
1. Ask per `jsc-ask:ask` rules what this delivery must contain. The options are fixed: **1. API 文件** and **2. 由使用者輸入**. State the impact scope on each. **Never assume the type, and never skip this — the answer decides what the whole package produces.**
|
|
2. Required fields, sample-data order and the new-versus-existing parameter marking: `references/deliver-formats.md`.
|
|
3. Completion condition: the confirmed type is written into the analysis page's 交付型別 column and saved back to the wiki before the first todo starts.
|
|
8. **Create the worktree — before touching any code.** Run `git fetch --prune origin` (this fetch is deliberate: the worktree must start from the newest remote state), then reuse the source branch confirmed in step 5 and the repository list read in step 2.1 — never read them off the page a second time. Ask per `jsc-ask:ask` rules how to handle the branch. **A multi-repository analysis builds its worktrees concurrently**; the repositories do not depend on each other. Path layout, the two `git worktree add` options, quoting, `.git/info/exclude` and the reporting duty: `references/branch.md`. Completion condition: every repository the analysis page names has a worktree built from `origin/{source-branch}`, and you have reported each worktree's path, checked-out branch, source branch and starting commit sha.
|
|
9. **Complete the work package's open items one at a time. Every item MUST run as a sub agent**, working inside the worktree:
|
|
1. One sub agent takes one item and follows the TDD loop: red before green, one vertical slice. Rules and anti-patterns: `references/tdd.md` (refactoring belongs to the review stage).
|
|
2. The main agent keeps only the wiki bookkeeping: when the sub agent reports the item done, flip its `[ ]` to `[x]` on the analysis page and save to the wiki.
|
|
3. **A code comment states why the code is written this way; it never states where the work is documented.** The tracking numbers this stage always holds — the work package number, the analysis page number, the TDD todo number, the source branch name and the PR number — stay out of every code comment; write the reason itself into the comment instead. Full list and the allowed exceptions: `jsc-review/references/comment-scope.md`. `jsc-hooks/hooks/comment-scope.sh` is wired on all five CLIs, but **it fires at a different moment on each, so never treat it as one uniform warning**: only claude scans the file the instant it is written, through `PostToolUse`; codex sweeps the whole worktree at the end of every turn, kiro at the next prompt submit, and copilot and antigravity only once when the session ends. Fix whatever it flags at once, then carry on with the same item. On the four CLIs that are not claude, none of that lands while the item is still being written, so **the one pass that still arrives in time is the `comment-scope.sh sweep` that `jsc-git:commit` runs before it commits at step 11.1** — that sweep is what keeps a flagged comment out of the commit, and a line it flags is fixed there, never waived. Completion condition: the item's own diff holds no comment line carrying any of those numbers, every warning the hook printed for this item is fixed, and on a CLI other than claude you have reported that the step 11.1 sweep is the pass being relied on.
|
|
4. Completion condition: every item of the package shows `[x]` on the saved analysis page, and each save happened before the next item's sub agent started.
|
|
10. **Two closing audits, side by side — a work package is finished only when both of them clear. Neither replaces the other, and neither waits for the other**:
|
|
1. **Code review** — when all items are done, call `jsc-review:code-review` over the work package's diff and wait for the verdict. The comment rule of step 9.3 is that review's own group, and `jsc-git:commit` sweeps the whole tree again at step 11.1, so this step runs no separate comment sweep of its own. Each round of fixes **MUST run as a sub agent** inside the same worktree. Completion condition: the review returned a passing verdict.
|
|
2. **API document audit — on a project that supports Swagger, the work package stays unfinished until its controller files are fully documented.** Whether the project supports Swagger is decided in code by `jsc-review/tools/swagger-detect.sh {worktree path}`; run it and branch on its exit code instead of judging the project yourself:
|
|
- `0` — the project supports Swagger. Call `jsc-review:api-doc` over the work package's changed controller files and wait for its verdict. What that audit checks belongs to `jsc-review:api-doc`; read the items there and keep no copy of them here.
|
|
- `1` — the project does not support Swagger. **Skip this audit explicitly and report the skip.** A reported skip is a pass, never a failure.
|
|
- `2` — bad arguments or a bad path. Fix them and run the script again; an undecidable detection is neither a pass nor a skip.
|
|
A failing verdict is fixed, never waived: each round of fixes **MUST run as a sub agent** inside the same worktree, and `jsc-review:api-doc` runs again over the fixed files until it passes.
|
|
Completion condition: `swagger-detect.sh` has run for this worktree and its exit code is reported, and either `jsc-review:api-doc` returned a passing verdict, or the skip is reported together with the exit code that caused it.
|
|
3. **Start both audits together and let them run side by side** — they read the same diff and neither one's verdict changes the other's input, so the closing wait costs one audit, not two. Completion condition: both audits have returned, and both cleared — a pass from `code-review`, and either a pass or a reported skip from the API document audit.
|
|
11. **One work package finished → commit, push, PR back to the source branch, then hold on that PR until it merges**:
|
|
1. Call `jsc-git:pr` from inside the worktree, **passing `{source-branch}` as the base branch**. One package, one PR; the branch ladder and how the base is derived are in `references/branch.md`.
|
|
2. Write the PR URL and number into that work package's PR column on the analysis page and save it back to the wiki, so the next run of this skill can find it (step 2).
|
|
3. Run `jsc-sdlc/tools/wp-gate.sh lock {owner}/{repo} {index} --wp {wp-number}`. The lock is what makes step 2's gate hold across work sessions — a new session starts blocked until that PR merges — and `--wp` is what hangs this PR on the claim from step 4.5, so `owns` can keep other sessions off it. Leave `--wp` out and every session is free to touch this PR. Branch on the exit code: exit 0 (`status=locked`) → proceed. Exit 2 (`status=usage`) → fix the arguments and run it again. Exit 3 (`status=missing-dep`) → the lock could not be recorded; report it and stop, because without the lock the next session starts unblocked on a PR that has not merged. Completion condition: the script printed `status=locked` and named the work package.
|
|
4. **The work package is finished the moment its PR is open — call `jsc-log:worklog` now**, under the Rules section's one-task-one-entry rule, reusing the PLAN and ANALYZE wiki repositories and page URLs resolved for this package in step 2.10. Completion condition: the entry is saved on `LOG_{HASH}` before the wait starts.
|
|
5. **Wait for the merge with `jsc-gitea/tools/pr-watch.sh {owner}/{repo} {index}`** — it polls every 60 seconds (`JSC_PR_WATCH_INTERVAL` overrides), never times out, and never repeats a comment it already reported. Branch on its exit code:
|
|
- `0` — the PR merged or was closed. Run `jsc-sdlc/tools/wp-gate.sh check {owner}/{repo} {index}` to tell merged from closed-unmerged, release the lock and hand the claim back. `status=merged` → remove the worktree (`references/branch.md`) and mark the package done on the analysis page; `status=closed-unmerged` → report it and stop, closed without merging is not finished. Comments printed in that final round still get an outcome per step 2.6 to 2.10.
|
|
- `10` — new comments are waiting. Run step 2.5 to 2.10 over them (ownership, consensus, sub agent fixes, outcomes, timestamp, work log), then run `pr-watch.sh` again. Repeat for as many rounds as the reviewer needs.
|
|
- `3` — the PR could not be found. Report and stop; a PR nobody can find never counts as merged.
|
|
- `2` — bad arguments, or Gitea was unreachable on the very first poll. Fix the arguments or the environment and run it again; never fall back to eyeballing the PR page and calling it merged.
|
|
6. **Do not start another work package in this session.** An unrelated package can still proceed, but in its own session with its own worktree; packages that depend on this one stay blocked until step 2 or step 11.5 sees it merged.
|
|
7. Completion condition: the PR exists, its URL is saved on the analysis page and reported to the user with the table format in `jsc-meta/references/pr-report.md`, the lock existed (`status=locked`), the work log entry is saved, and `pr-watch.sh` has returned `0` with `wp-gate.sh check` confirming `status=merged` — or the run stopped on a reported `2`, `3` or `status=closed-unmerged`.
|
|
12. **Deliver the document, then register for maintenance** — one closing pass over the two questions this stage owes the user. A finished work package is a delivery, so **always ask before producing it; never pick a format silently and never skip either question**:
|
|
1. Ask per `jsc-ask:ask` rules which delivery format to produce. The options are fixed: **a `DELIVER_{HASH}` wiki page** or **a Gitea issue comment**. State the impact scope on each (the wiki page lives beside the plan and analysis pages; the issue comment reaches whoever follows that issue).
|
|
2. Both formats use the same structure — `templates/deliver-page.md`, in Traditional Chinese. Only the destination differs. Sample values and personal-data handling: `references/deliver-formats.md`.
|
|
3. Wiki page: write `DELIVER_{HASH}` through `jsc-gitea:wiki`, where `{HASH}` comes from `jsc-gitea/tools/hash-id` over `{owner}/{repo}` plus the work package number (for example `plugins/sdlc#WP-01`), so each work package gets its own page instead of overwriting the previous one. Then upsert this work package's row in `DELIVER_CONTENTS` per `templates/deliver-contents.md` — add the row if missing, otherwise refresh it — following "Contents pages are appended, never overwritten" below.
|
|
4. Issue comment: confirm the issue number with the user (propose the one referenced by the work package or the PR; never guess), then post via `jsc-gitea/tools/gitea.sh api POST /repos/{owner}/{repo}/issues/{n}/comments` with the body passed in as a UTF-8 file — real newlines, never a literal `\n`.
|
|
5. With the delivery produced, ask per `jsc-ask:ask` rules whether to register this project for maintenance: upsert this repository's row in `MAINTAIN_CONTENTS` with `templates/maintain-contents.md` — add the row if missing, otherwise refresh it — following "Contents pages are appended, never overwritten" below. Required: repository `{owner}/{repo}`, maintenance method, start date. Optional: end date (NULL = maintain forever), last-maintained time.
|
|
6. Completion condition: the chosen delivery format has actually been produced and you have reported where it landed (wiki page name, or the comment URL), **and** the user has answered the maintenance question with a chosen registration saved on the wiki.
|
|
13. **Stage report — the last thing this stage does, including every early stop** (the work package gate blocked, no work package was selectable, the source branch was missing from the remote, a wiki read or write failed). Run `tools/stage-report.sh implement` with:
|
|
- one `--page TYPE:{page}` per wiki page this run wrote — `ANALYZE_{HASH}`, `DELIVER_{HASH}` and `DELIVER_CONTENTS`, `MAINTAIN_CONTENTS`;
|
|
- `--worklog` and `--worklog-heading` pointing at the entry step 11.4 wrote — following the Rules section's one-task-one-entry rule, a stage that finished anything already has one. `--pending-file {file} --log-hash {HASH}` is the fallback for a stage that stopped before any task finished: it holds the content for the next `jsc-log:worklog` run, and held content is not a written log;
|
|
- `--worktree {path} --source-branch {name} --work-branch {name} --pr {url}` — the script reads the commit count, the push state and whether the source branch exists on the remote by itself, so pass the names, not your own count.
|
|
|
|
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 it names the worktree, all three branches and every wiki page this run wrote.
|
|
|
|
## Contents pages are appended, never overwritten
|
|
|
|
`DELIVER_CONTENTS` and `MAINTAIN_CONTENTS` are shared directories: every row on them belongs to somebody's work package or repository, and this run reads none of those rows from anywhere else. So every write to them is an upsert of one row on top of the content just read — add the row if missing, otherwise refresh it, then `wiki-put` the whole page. Whole-page overwrite is forbidden, and a row this run does not own stays untouched.
|
|
|
|
That rests entirely on reading the old page back, so branch the `wiki-get` on its exit code:
|
|
|
|
| Exit | What this step does |
|
|
| --- | --- |
|
|
| 0 | the page is there — upsert this run's row into the content that came back, then write the whole page |
|
|
| 4 | the page really does not exist yet — this is the **only** code that permits building it from the template |
|
|
| 7 | the key is invalid or lacks permission — stop, report the code and its cause, create no page and write nothing |
|
|
| 8 | any other API failure — same as 7: stop and report, and do not retry the same call unchanged |
|
|
|
|
Why 7 and 8 abort: both mean the old content is unknown, not that the page is missing. Reading either as "not there yet" makes the step write a fresh template over a live directory, and every other work package's row is gone — the write carries no merge and no backup. `DELIVER_{HASH}` is the opposite case: it is a content page belonging to one work package, so writing it whole is correct. The distinction is the page, not the write.
|
|
|
|
Completion condition: every contents-page write this stage made names the `wiki-get` exit code it branched on, and no page was created on any code other than 4.
|
|
|
|
## Rules
|
|
|
|
- **One finished task, one work log entry.** A task is one of three things: one work package, one round of PR-comment fixes, or one standalone fix commit. Call `jsc-log:worklog` the moment one of them finishes — never let a stage end and then write a single catch-up entry, because by then the elapsed time, the token counts and the difficulties are gone. Every entry appends to the same `LOG_{HASH}` page, so one package that took five comment rounds leaves five entries. The PLAN and ANALYZE wiki repositories and page URLs are resolved once per work package and reused by every entry of that package; only a change of repository forces a fresh resolution. Content parked earlier by `tools/stage-report.sh --pending-file` is merged into that same write and cleared only once the write succeeds; parked content is not a written log.
|
|
- The work ticket is a mutex: always skip work packages that already hold a ticket; never take one over. Between the claim (step 4.5) and the ticket write (step 6), `wp-gate.sh claim` is what holds the package — the claim is recorded in code, so a second session sees it even before the ticket reaches the page.
|
|
- Never batch wiki updates across items; one item, one update.
|
|
- Sample data written into code or fixtures follows the analysis page's 資料來源 column, under the rules in `references/deliver-formats.md`.
|
|
- Everything the skill writes out (wiki content, commit messages, PR descriptions) stays Traditional Chinese per the STE100 rule.
|
|
|
|
## What the single-key source-branch confirmation gives up
|
|
|
|
Step 5.2 used to run a full decision tree that made the user say out loud that the source branch is **also the PR target**, every run. That explicit two-way confirmation is gone: a user who taps the confirm key now agrees to the analysis page's recorded branch as the PR target without being asked about the target separately. A stale or wrong PR target on the analysis page therefore reaches the PR unchallenged. The two exception cases in step 5.2 — no recorded branch, and a branch missing from the remote — are what remains of that guard, and they keep the full decision tree.
|