From 7015fc4a2c5d8ae3b9155ff1105bed45b3835cae Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sun, 18 Oct 2026 23:47:10 +0000 Subject: [PATCH 1/3] =?UTF-8?q?Fix:=20bump=20=E3=81=A7=E6=AD=A3=E5=BC=8F?= =?UTF-8?q?=E7=89=88=E3=81=AE=E8=A1=8C=E3=81=8C=E9=96=8B=E7=99=BA=E7=89=88?= =?UTF-8?q?=E3=81=AE=E4=BE=8B=E3=81=AB=E8=BF=BD=E3=81=84=E3=81=A4=E3=81=84?= =?UTF-8?q?=E3=81=9F=E3=82=89=E4=BE=8B=E3=81=AE=E5=9F=BA=E5=BA=95=E3=82=92?= =?UTF-8?q?=E6=AC=A1=E3=81=AE=20MINOR=20=E3=81=B8=E9=80=B2=E3=82=81?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10.18.0 → 10.19.0-dev.1 の bump で正式版の行だけが 10.19.0 になり、開発版・確認版の例(10.19.0-dev.1 / -rc.1)が 正式版より新しくなくなって check-doc-staleness.py が落ちた。章の例(表・次の開発の例・接尾辞を外す例・順序の例)の 基底を一緒に進める。 Co-Authored-By: Claude Opus 5.5 --- plugins/ndf/scripts/release-steps.py | 46 ++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/plugins/ndf/scripts/release-steps.py b/plugins/ndf/scripts/release-steps.py index 92759fe05..22f571b96 100755 --- a/plugins/ndf/scripts/release-steps.py +++ b/plugins/ndf/scripts/release-steps.py @@ -327,8 +327,16 @@ def base_version(root, pdir, ref): return None +def _ver_key(v): + return tuple(int(x) for x in v.split(".")) + + def bump_versioning_doc(ed): - """docs/versioning-and-distribution.md の「版の付け方と開発版の配布」章の正式版の版数。""" + """docs/versioning-and-distribution.md の「版の付け方と開発版の配布」章の正式版の版数。 + + 正式版の行が開発版・公開前の確認版の例の基底に追いついたら、例(表の 2 行・次の開発の例・接尾辞を外す例・ + 順序の例)の基底を次の MINOR へ進める(check-doc-staleness.py の「正式版の行より新しい版」を保つ)。 + """ doc = ed.root / "docs" / "versioning-and-distribution.md" rel = "docs/versioning-and-distribution.md" ob, nb = base_of(ed.old), base_of(ed.new) @@ -338,16 +346,41 @@ def bump_versioning_doc(ed): ed.manual.append(f"{rel} が無い(この章は手で直す)") return lines = ed.lines(doc) + head = next((i for i, l in enumerate(lines) if l.startswith("## 版の付け方と開発版の配布")), None) + if head is None: + ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章が無い(この章は手で直す)") + return + tail = next((i for i in range(head + 1, len(lines)) if lines[i].startswith("## ")), len(lines)) + dev_rows = [l for l in lines[head:tail] if re.match(r"^\| 開発版 \| `", l)] + m = re.search(r"`(\d+\.\d+\.\d+)-dev\.\d+`", dev_rows[0]) if len(dev_rows) == 1 else None + example = m.group(1) if m else None + advance = None + if example is None: + ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章の開発版の行が特定できない(この章は手で直す)") + elif _ver_key(example) <= _ver_key(nb): + if example == ob: + ed.manual.append(f"{rel}: 開発版の例の基底 {example} が旧版と同じ(この章は手で直す)") + else: + major, minor, _ = _ver_key(nb) + nxt = f"{major}.{minor + 1}.0" + ex_rx = re.compile(r"`" + re.escape(example) + r"((?:-(?:dev|rc)\.\d+)?)`") + advance = (ex_rx, nxt) + + def advanced(line): + return advance[0].sub(lambda mm: f"`{advance[1]}{mm.group(1)}`", line) if advance else line + targets = [ (re.compile(r"^\| 正式版 \| `([^`]+)` \|"), "正式版の表の行"), (re.compile(r"`([^`]+)` の次を開発するなら"), "接尾辞の例"), ] + done = set() for rx, what in targets: - hits = [i for i, l in enumerate(lines) if rx.search(l)] + hits = [i for i in range(head, tail) if rx.search(lines[i])] if len(hits) != 1: ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章の{what}が特定できない(この章は手で直す)") continue i = hits[0] + done.add(i) cur = rx.search(lines[i]).group(1) if cur == nb: continue @@ -355,7 +388,14 @@ def bump_versioning_doc(ed): ed.manual.append(f"{rel}: {what}の版が {cur} で旧版 {ob} と違う(この章は手で直す)") continue esc = bump.braces(lines[i]) - ed.place(doc, [i], esc.replace(f"`{ob}`", f"`{bump.CUR_BASE}`", 1), esc.replace(f"`{ob}`", f"`{bump.NEW_BASE}`", 1), what) + to = bump.braces(advanced(lines[i])) + ed.place(doc, [i], esc.replace(f"`{ob}`", f"`{bump.CUR_BASE}`", 1), to.replace(f"`{ob}`", f"`{bump.NEW_BASE}`", 1), what) + if advance is None: + return + for i in range(head, tail): + if i in done or advanced(lines[i]) == lines[i] or lines[i].startswith("```"): + continue + ed.place(doc, [i], bump.braces(lines[i]), bump.braces(advanced(lines[i])), "開発版の例") def plan_bump(root, pdir, plugin, old, new): From 003a6609da9e64fff2bdd864c3a434219b3ea853 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sun, 18 Oct 2026 23:48:58 +0000 Subject: [PATCH 2/3] Release: ndf v10.19.0-dev.1 --- .claude-plugin/marketplace.json | 2 +- CHANGELOG.md | 7 +++++++ README.md | 4 ++-- docs/versioning-and-distribution.md | 12 ++++++------ plugins/ndf/.claude-plugin/plugin.json | 4 ++-- plugins/ndf/.codex-plugin/plugin.json | 4 ++-- plugins/ndf/README.md | 8 ++++---- plugins/ndf/dev.agy/plugin.json | 4 ++-- 8 files changed, 26 insertions(+), 19 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 69e9806d5..66fb3eb80 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ { "name": "ndf", "source": "./plugins/ndf", - "description": "Claude Code plugin (v10.18.0): 8 specialized agents (plus 1 worker agent for the 3-layer workflow) and 48 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, statusline, external AI delegation (Codex/agy), transcript retention guard, and optional Slack notifications.", + "description": "Claude Code plugin (v10.19.0-dev.1): 8 specialized agents (plus 1 worker agent for the 3-layer workflow) and 48 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, statusline, external AI delegation (Codex/agy), transcript retention guard, and optional Slack notifications.", "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d034fcaa..9bd02b60d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ **開発版(接尾辞の付いた版)は載せない。** `9.8.0` は `9.8.0-dev.1` までしか出ておらず、 その内容は `10.0.0` で届いている。 +## [ndf 10.19.0] - 2026-10-18 + +- ndf の release Skill に、スライドの汎用テンプレートが入りました。ページの枠組みに沿って生成スクリプトから pptx を作り、トーン&マナーを差し替えられます。台本はノートになり、台本から発表の尺を計算できます(#2069)(#2070) +- スライドの生成は生成スクリプトの 1 経路です。構成メモと台本を用意し、生成スクリプトで作ります(#2069)(#2070) +- Google Slides の全ページのサムネイルを取るスクリプトで、変換後の体裁を画像で確かめられます。pptx の変換と差し替えに使う gws のコマンドは対応表から引けます(#2069)(#2070) +- 既知の失敗に、pptx で差し替えた Google スライドの書体が Arial になる場合と、その確かめ方を載せています(#2069)(#2070) + ## [ndf 10.18.0] - 2026-10-16 - Update: Bump actions/setup-python from 5 to 7(#1387) diff --git a/README.md b/README.md index f438f55af..5d4728607 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Claude Code では `/ndf:` と打って呼びます。**Skill** は | プラグイン名 | バージョン | できること | 詳細 | | --- | --- | --- | --- | -| **ndf** | 10.18.0 | 開発の作業手順(Skill)と専門のサブエージェント。4 つの AI ツールへ同じ名前で入る | [README](./plugins/ndf/README.md) | +| **ndf** | 10.19.0-dev.1 | 開発の作業手順(Skill)と専門のサブエージェント。4 つの AI ツールへ同じ名前で入る | [README](./plugins/ndf/README.md) | | **playwright-kit** | 3.0.1 | Playwright による E2E テストの計画・スクリプト作成・証跡のレポート | [README](./plugins/playwright-kit/README.md) | 外部サービスへつなぐ MCP サーバーの設定のプラグインが 10 個あります(Claude Code / Codex / Kiro CLI 向け)。 @@ -88,7 +88,7 @@ Claude Code では `/ndf:` と打って呼びます。**Skill** は ### NDF プラグインの Skill の一覧 -**NDFプラグイン v10.18.0** に入る Skill の数は、AI ツールごとに違います。 +**NDFプラグイン v10.19.0-dev.1** に入る Skill の数は、AI ツールごとに違います。 Claude Code向け core 48個、Kiro向け core 45個、Codex向け core 44個、agy向け core 44個です。 元Skills(48個)の内訳は次のとおりです。 - Pull Request とレビュー (7): pr, pr-tests, fix, pr-review, cherry-pick-pr, deploy, merged diff --git a/docs/versioning-and-distribution.md b/docs/versioning-and-distribution.md index fd428ea41..2704ba6ee 100644 --- a/docs/versioning-and-distribution.md +++ b/docs/versioning-and-distribution.md @@ -57,15 +57,15 @@ semver の順序で除外されるのは、プラグイン間の依存解決(` | 版 | 形 | 意味 | | --- | --- | --- | -| 正式版 | `10.18.0` | 利用者が常用してよい | -| 開発版 | `10.19.0-dev.1` | 検証中。入れたくない利用者は取得を控えられる | -| 公開前の確認版 | `10.19.0-rc.1` | 正式版の候補。残るのは確認だけ | +| 正式版 | `10.19.0` | 利用者が常用してよい | +| 開発版 | `10.20.0-dev.1` | 検証中。入れたくない利用者は取得を控えられる | +| 公開前の確認版 | `10.20.0-rc.1` | 正式版の候補。残るのは確認だけ | -- 接尾辞は**次に出す正式版の版数へ付ける**。`10.18.0` の次を開発するなら `10.19.0-dev.1` +- 接尾辞は**次に出す正式版の版数へ付ける**。`10.19.0` の次を開発するなら `10.20.0-dev.1` - 連番は開発版を出すたびに増やす。**同じ版数で中身を差し替えない**。差し替えると、利用者の 手元にある版と `main` の版が同じ番号で別物になり、何を確かめたのかが分からなくなる -- **正式版を出すときは接尾辞を外す。** `10.19.0-dev.3` の次は `10.19.0` -- 順序は semver に従い `10.19.0-dev.1` < `10.19.0-rc.1` < `10.19.0` になる +- **正式版を出すときは接尾辞を外す。** `10.20.0-dev.3` の次は `10.20.0` +- 順序は semver に従い `10.20.0-dev.1` < `10.20.0-rc.1` < `10.20.0` になる ## ランタイムごとの取得と導入 diff --git a/plugins/ndf/.claude-plugin/plugin.json b/plugins/ndf/.claude-plugin/plugin.json index 22c78e780..912d5402f 100644 --- a/plugins/ndf/.claude-plugin/plugin.json +++ b/plugins/ndf/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "ndf", - "version": "10.18.0", - "description": "Claude Code plugin (v10.18.0): 8 specialized agents (plus 2 supervisor agents and 1 worker agent for the 3-layer workflow) and 48 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, statusline, external AI delegation (Codex/agy), transcript retention guard, and optional Slack notifications.", + "version": "10.19.0-dev.1", + "description": "Claude Code plugin (v10.19.0-dev.1): 8 specialized agents (plus 2 supervisor agents and 1 worker agent for the 3-layer workflow) and 48 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, statusline, external AI delegation (Codex/agy), transcript retention guard, and optional Slack notifications.", "author": { "name": "takemi-ohama", "url": "https://github.com/takemi-ohama" diff --git a/plugins/ndf/.codex-plugin/plugin.json b/plugins/ndf/.codex-plugin/plugin.json index b43323a5d..66db5606e 100644 --- a/plugins/ndf/.codex-plugin/plugin.json +++ b/plugins/ndf/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "ndf", - "version": "10.18.0", - "description": "Codex plugin (v10.18.0): 44 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, external AI delegation (Codex/agy), and optional Slack completion notifications.", + "version": "10.19.0-dev.1", + "description": "Codex plugin (v10.19.0-dev.1): 44 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, external AI delegation (Codex/agy), and optional Slack completion notifications.", "skills": [ "./skills/cherry-pick-pr", "./skills/cross-refactoring", diff --git a/plugins/ndf/README.md b/plugins/ndf/README.md index cc34a36aa..add8da887 100644 --- a/plugins/ndf/README.md +++ b/plugins/ndf/README.md @@ -89,7 +89,7 @@ bash plugins/ndf/dev.kiro/install.sh --dry-run ```bash python3 -c "import json;print(json.load(open('.kiro/agents/ndf.json'))['description'])" -# => NDF統合開発エージェント(Kiro CLI用 / v10.18.0) +# => NDF統合開発エージェント(Kiro CLI用 / v10.19.0-dev.1) ``` ### agy @@ -412,7 +412,7 @@ agy models # 認証確認 ```text # 動く: 実体パスを示して読ませる -~/.codex/plugins/cache/ai-plugins/ndf/10.18.0/skills/deploy/SKILL.md を読んで、その手順どおりに qa/staging へ deploy PR を作成してください。 +~/.codex/plugins/cache/ai-plugins/ndf/10.19.0-dev.1/skills/deploy/SKILL.md を読んで、その手順どおりに qa/staging へ deploy PR を作成してください。 # 動かない: 明示起動 ($ は展開されない) $deploy qa/staging @@ -434,14 +434,14 @@ marketplace 経由でインストールした場合、Skill の実体は **ワ ```text $CODEX_HOME/plugins/cache////skills//SKILL.md # 既定 ($CODEX_HOME=~/.codex) の例: -# ~/.codex/plugins/cache/ai-plugins/ndf/10.18.0/skills/deploy/SKILL.md +# ~/.codex/plugins/cache/ai-plugins/ndf/10.19.0-dev.1/skills/deploy/SKILL.md ``` そのため「`deploy` の SKILL.md を探して読んで」のような曖昧な依頼は、Codex のファイル探索がワークスペース内に限られる状況では失敗しえます。**抑止した Skill は `$` が展開されない**ので、`codex plugin list` で実体パスを確認し、絶対パスを渡してください。 ```bash codex plugin list | grep 'ndf@ai-plugins' -# => ndf@ai-plugins installed, enabled 10.18.0 +# => ndf@ai-plugins installed, enabled 10.19.0-dev.1 ``` 抑止していない Skill(`markdown-writing` など)はキャッシュ配下でも `$` で解決するため、そちらは `$` 起動が使えます。 diff --git a/plugins/ndf/dev.agy/plugin.json b/plugins/ndf/dev.agy/plugin.json index 6605b3baf..708235604 100644 --- a/plugins/ndf/dev.agy/plugin.json +++ b/plugins/ndf/dev.agy/plugin.json @@ -1,5 +1,5 @@ { "name": "ndf", - "version": "10.18.0", - "description": "Antigravity CLI plugin (v10.18.0): 44 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, external AI delegation, and worktree guidance hooks." + "version": "10.19.0-dev.1", + "description": "Antigravity CLI plugin (v10.19.0-dev.1): 44 focused NDF skills for PR/review workflows, cross-review, implementation planning, plan-to-spec, Docker container access, external AI delegation, and worktree guidance hooks." } From 14a64a2f73fe3341942d52981b9ac9001f586829 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sun, 18 Oct 2026 23:51:25 +0000 Subject: [PATCH 3/3] =?UTF-8?q?Fix:=20=E7=89=88=E3=81=AE=E6=96=87=E6=9B=B8?= =?UTF-8?q?=E3=81=AE=E6=9B=B8=E3=81=8D=E6=8F=9B=E3=81=88=E3=82=92=20releas?= =?UTF-8?q?e=5Flib/bump.py=20=E3=81=B8=E7=A7=BB=E3=81=97=E3=80=81=E5=9B=B2?= =?UTF-8?q?=E3=81=BF=E3=81=AE=E5=88=A4=E5=AE=9A=E3=82=92=20lib/md.py=20?= =?UTF-8?q?=E3=81=AB=E4=BB=BB=E3=81=9B=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release-steps.py が例外リストの行数を超え、``` の判定を自前で持っていたため script-structure-check が落ちた(PR #2073)。 Co-Authored-By: Claude Opus 5.5 --- plugins/ndf/scripts/release-steps.py | 73 +----------------------- plugins/ndf/scripts/release_lib/bump.py | 75 ++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 73 deletions(-) diff --git a/plugins/ndf/scripts/release-steps.py b/plugins/ndf/scripts/release-steps.py index 22f571b96..dd7906d44 100755 --- a/plugins/ndf/scripts/release-steps.py +++ b/plugins/ndf/scripts/release-steps.py @@ -327,77 +327,6 @@ def base_version(root, pdir, ref): return None -def _ver_key(v): - return tuple(int(x) for x in v.split(".")) - - -def bump_versioning_doc(ed): - """docs/versioning-and-distribution.md の「版の付け方と開発版の配布」章の正式版の版数。 - - 正式版の行が開発版・公開前の確認版の例の基底に追いついたら、例(表の 2 行・次の開発の例・接尾辞を外す例・ - 順序の例)の基底を次の MINOR へ進める(check-doc-staleness.py の「正式版の行より新しい版」を保つ)。 - """ - doc = ed.root / "docs" / "versioning-and-distribution.md" - rel = "docs/versioning-and-distribution.md" - ob, nb = base_of(ed.old), base_of(ed.new) - if ob == nb: - return - if not doc.is_file(): - ed.manual.append(f"{rel} が無い(この章は手で直す)") - return - lines = ed.lines(doc) - head = next((i for i, l in enumerate(lines) if l.startswith("## 版の付け方と開発版の配布")), None) - if head is None: - ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章が無い(この章は手で直す)") - return - tail = next((i for i in range(head + 1, len(lines)) if lines[i].startswith("## ")), len(lines)) - dev_rows = [l for l in lines[head:tail] if re.match(r"^\| 開発版 \| `", l)] - m = re.search(r"`(\d+\.\d+\.\d+)-dev\.\d+`", dev_rows[0]) if len(dev_rows) == 1 else None - example = m.group(1) if m else None - advance = None - if example is None: - ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章の開発版の行が特定できない(この章は手で直す)") - elif _ver_key(example) <= _ver_key(nb): - if example == ob: - ed.manual.append(f"{rel}: 開発版の例の基底 {example} が旧版と同じ(この章は手で直す)") - else: - major, minor, _ = _ver_key(nb) - nxt = f"{major}.{minor + 1}.0" - ex_rx = re.compile(r"`" + re.escape(example) + r"((?:-(?:dev|rc)\.\d+)?)`") - advance = (ex_rx, nxt) - - def advanced(line): - return advance[0].sub(lambda mm: f"`{advance[1]}{mm.group(1)}`", line) if advance else line - - targets = [ - (re.compile(r"^\| 正式版 \| `([^`]+)` \|"), "正式版の表の行"), - (re.compile(r"`([^`]+)` の次を開発するなら"), "接尾辞の例"), - ] - done = set() - for rx, what in targets: - hits = [i for i in range(head, tail) if rx.search(lines[i])] - if len(hits) != 1: - ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章の{what}が特定できない(この章は手で直す)") - continue - i = hits[0] - done.add(i) - cur = rx.search(lines[i]).group(1) - if cur == nb: - continue - if cur != ob: - ed.manual.append(f"{rel}: {what}の版が {cur} で旧版 {ob} と違う(この章は手で直す)") - continue - esc = bump.braces(lines[i]) - to = bump.braces(advanced(lines[i])) - ed.place(doc, [i], esc.replace(f"`{ob}`", f"`{bump.CUR_BASE}`", 1), to.replace(f"`{ob}`", f"`{bump.NEW_BASE}`", 1), what) - if advance is None: - return - for i in range(head, tail): - if i in done or advanced(lines[i]) == lines[i] or lines[i].startswith("```"): - continue - ed.place(doc, [i], bump.braces(lines[i]), bump.braces(advanced(lines[i])), "開発版の例") - - def plan_bump(root, pdir, plugin, old, new): """`plugin` の版を `old` から `new` へ上げる箇所を集めた `BumpPlan` を返す(まだ書き換えない)。""" ed = bump.BumpPlan(root, old, new) @@ -436,7 +365,7 @@ def plan_bump(root, pdir, plugin, old, new): ed.sub(nr, r"(Kiro CLI用 / v", "plugins/ndf/README.md の Kiro の確認例") ed.sub(nr, r"/plugins/cache/ai-plugins/ndf/", "plugins/ndf/README.md の Codex のパス例", count=2) ed.sub(nr, r"ndf@ai-plugins\s+installed", "plugins/ndf/README.md の codex plugin list の出力例") - bump_versioning_doc(ed) + bump.versioning_doc(ed) return ed diff --git a/plugins/ndf/scripts/release_lib/bump.py b/plugins/ndf/scripts/release_lib/bump.py index f365b5357..716beaace 100644 --- a/plugins/ndf/scripts/release_lib/bump.py +++ b/plugins/ndf/scripts/release_lib/bump.py @@ -14,8 +14,9 @@ import tempfile from pathlib import Path +import md import versions -from step_result import EXIT_PRECONDITION, StepError, plugin_dir +from step_result import EXIT_PRECONDITION, StepError, base_of, plugin_dir def ver_pat(v): @@ -154,3 +155,75 @@ def require_bumped(root, plugin, ver): raise StepError(f"plugin.json の版を読めない: {e}", EXIT_PRECONDITION) if got != ver: raise StepError(f"{plugin} の plugin.json の版が {got} で、今回の版 {ver} でない(bump が通っていない)", EXIT_PRECONDITION) + + +def _ver_key(v): + return tuple(int(x) for x in v.split(".")) + + +def versioning_doc(ed): + """docs/versioning-and-distribution.md の「版の付け方と開発版の配布」章の正式版の版数。 + + 正式版の行が開発版・公開前の確認版の例の基底に追いついたら、例(表の 2 行・次の開発の例・接尾辞を外す例・ + 順序の例)の基底を次の MINOR へ進める(check-doc-staleness.py の「正式版の行より新しい版」を保つ)。 + """ + doc = ed.root / "docs" / "versioning-and-distribution.md" + rel = "docs/versioning-and-distribution.md" + ob, nb = base_of(ed.old), base_of(ed.new) + if ob == nb: + return + if not doc.is_file(): + ed.manual.append(f"{rel} が無い(この章は手で直す)") + return + lines = ed.lines(doc) + fenced = md.fenced_lines("\n".join(lines)) + head = next((i for i, l in enumerate(lines) if l.startswith("## 版の付け方と開発版の配布")), None) + if head is None: + ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章が無い(この章は手で直す)") + return + tail = next((i for i in range(head + 1, len(lines)) if lines[i].startswith("## ")), len(lines)) + dev_rows = [l for l in lines[head:tail] if re.match(r"^\| 開発版 \| `", l)] + m = re.search(r"`(\d+\.\d+\.\d+)-dev\.\d+`", dev_rows[0]) if len(dev_rows) == 1 else None + example = m.group(1) if m else None + advance = None + if example is None: + ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章の開発版の行が特定できない(この章は手で直す)") + elif _ver_key(example) <= _ver_key(nb): + if example == ob: + ed.manual.append(f"{rel}: 開発版の例の基底 {example} が旧版と同じ(この章は手で直す)") + else: + major, minor, _ = _ver_key(nb) + nxt = f"{major}.{minor + 1}.0" + ex_rx = re.compile(r"`" + re.escape(example) + r"((?:-(?:dev|rc)\.\d+)?)`") + advance = (ex_rx, nxt) + + def advanced(line): + return advance[0].sub(lambda mm: f"`{advance[1]}{mm.group(1)}`", line) if advance else line + + targets = [ + (re.compile(r"^\| 正式版 \| `([^`]+)` \|"), "正式版の表の行"), + (re.compile(r"`([^`]+)` の次を開発するなら"), "接尾辞の例"), + ] + done = set() + for rx, what in targets: + hits = [i for i in range(head, tail) if rx.search(lines[i])] + if len(hits) != 1: + ed.manual.append(f"{rel}: 「版の付け方と開発版の配布」章の{what}が特定できない(この章は手で直す)") + continue + i = hits[0] + done.add(i) + cur = rx.search(lines[i]).group(1) + if cur == nb: + continue + if cur != ob: + ed.manual.append(f"{rel}: {what}の版が {cur} で旧版 {ob} と違う(この章は手で直す)") + continue + esc = braces(lines[i]) + to = braces(advanced(lines[i])) + ed.place(doc, [i], esc.replace(f"`{ob}`", f"`{CUR_BASE}`", 1), to.replace(f"`{ob}`", f"`{NEW_BASE}`", 1), what) + if advance is None: + return + for i in range(head, tail): + if i in done or advanced(lines[i]) == lines[i] or (i < len(fenced) and fenced[i]): + continue + ed.place(doc, [i], braces(lines[i]), braces(advanced(lines[i])), "開発版の例")