Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# 独自スキルプラグイン開発の薦め
# 独自プラグイン開発の薦め

社外の勉強会・登壇で話す 23 ページのスライド。NDF の機能を例に、自分用のスキルプラグインを作って育てることを薦める。
社外の勉強会・登壇で話すスライド(台本の 21 ページと章扉 6 つの 27 ページ)。NDF の機能を例に、自分用のスキルを作り、プラグインにして配り、育てることを薦める。
`release` の `form-slide.md` の生成スクリプトの経路で作った。

| ファイル | 中身 |
| --- | --- |
| [script.md](script.md) | 台本(第 7 稿の写し)。ページごとの見出しと読み上げ。スピーカーノートの正本 |
| [notes.md](notes.md) | 構成メモ。ページごとの見出し・役割・根拠の表と、尺 |
| [notes.md](notes.md) | 構成メモ。ページごとの見出し・役割・根拠の表と、章立て・尺 |
| [slides/build-deck.js](slides/build-deck.js) | 生成スクリプト。スライドの正本 |
| [slides/theme.json](slides/theme.json) | トーン&マナーのファイル |
| `slides/lib/` | NDF の汎用テンプレートの枠組み(`release` の `assets/slides/lib/`)の写し。書き換えない |
Expand All @@ -28,7 +28,7 @@ Google Slides を成果物にする。pptx は生成スクリプトから作り
| 色 | 既定値 |
| 著作権表示 | `NDF — github.com/devbasex/ai-plugins` |
| ロゴ | なし |
| 写した時点の `lib/` の内容のハッシュ | `86c3acf6f8b74c80bb92ffa3a1dfe17cde6ee17d199e6f76d029744f7d6a9133`(`cat slides/lib/*.js \| sha256sum`) |
| 写した時点の `lib/` の内容のハッシュ | `e1fbac1642aef0fe49a57b00d7a2575eaf363bbfd5c55b324d53aa778f632800`(`cat slides/lib/*.js \| sha256sum`) |

## 生成と確認の手順

Expand Down
113 changes: 64 additions & 49 deletions docs/presentations/2026-10-17-skill-plugin-development/notes.md

Large diffs are not rendered by default.

62 changes: 27 additions & 35 deletions docs/presentations/2026-10-17-skill-plugin-development/script.md

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// - 書体と色の値は DEFAULT_THEME と theme.json だけが持つ。関数に渡す色は theme.colors の項目名で受ける
// - 台本(script.md)を渡すと、ページを作るたびに同じ番号の読み上げをスピーカーノートへ付け、
// 保存の前に台本のページ数と作ったページ数を照合する
// - 章扉(section)は構成を見せるページで、スピーカーノートを持たず、台本の番号を進めない。
// ページ数の照合からも外す(ページ番号は章扉も数える)
//
// 資料のディレクトリへ写して使う。写した後に書き換えない(プロジェクトの値は theme.json へ書く)。

Expand Down Expand Up @@ -242,7 +244,9 @@ function createDeck(opts) {
if (o.title) p.subject = o.title;
const F = theme.font;
const logo = theme.logo ? "image/png;base64," + fs.readFileSync(theme.logo).toString("base64") : null;
let pageNo = 0;
let pageNo = 0; // 作ったページ(章扉を含む)。ページ番号に使う
let scriptNo = 0; // 台本のページを消費したページ(章扉を除く)
let sections = 0;

function color(name) {
if (!(name in theme.colors)) throw new DeckError(`色は theme.colors の項目名で指す: ${name}`, EXIT_INPUT);
Expand Down Expand Up @@ -271,12 +275,18 @@ function createDeck(opts) {
return t.map((x) => (x && typeof x === "object" ? { ...x, options: resolve(x.options) } : x));
}

function newSlide() {
// withScript が false のページ(章扉)は台本の番号を進めず、ノートを持たない
function newSlide(withScript) {
const s = p.addSlide();
pageNo++;
s.background = { color: color("background") };
if (withScript === false) {
sections++;
return s;
}
scriptNo++;
if (script) {
const sp = script[pageNo - 1];
const sp = script[scriptNo - 1];
if (sp && sp.reading) s.addNotes(sp.reading);
}
return s;
Expand Down Expand Up @@ -322,7 +332,7 @@ function createDeck(opts) {
}

function section(title, sub) {
const s = newSlide();
const s = newSlide(false);
const c = FRAME.section;
s.addShape(p.ShapeType.rect, { ...c.band, fill: { color: color("accent") }, line: { type: "none" } });
putLogo(s, FRAME.logo);
Expand Down Expand Up @@ -366,11 +376,11 @@ function createDeck(opts) {

async function save(out) {
if (!out || !/\.pptx$/i.test(out)) throw new DeckError("出力のパスは .pptx で終える", EXIT_INPUT);
if (script && script.length !== pageNo) {
throw new DeckError(`ページ数が台本と合わない: 台本 ${script.length} ページ / 作ったページ ${pageNo}`, EXIT_INPUT);
if (script && script.length !== scriptNo) {
throw new DeckError(`ページ数が台本と合わない: 台本 ${script.length} ページ / 作ったページ ${scriptNo}(章扉 ${sections} を除く)`, EXIT_INPUT);
}
await p.writeFile({ fileName: out });
return { out, pages: pageNo };
return { out, pages: pageNo, sections };
}

return {
Expand All @@ -381,6 +391,9 @@ function createDeck(opts) {
get pageNo() {
return pageNo;
},
get scriptNo() {
return scriptNo;
},
color,
text,
cover,
Expand Down Expand Up @@ -410,7 +423,7 @@ function run(dir, opts, build) {
const deck = createDeck({ ...opts, theme, baseDir: dir });
await build(deck);
const r = await deck.save(out);
console.log(`${r.out}: ${r.pages} ページ`);
console.log(`${r.out}: ${r.pages} ページ(章扉 ${r.sections})`);
})().catch((e) => {
console.error(e.message);
process.exit(e instanceof DeckError ? e.code : 1);
Expand Down
2 changes: 1 addition & 1 deletion docs/presentations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

| 資料 | 内容 | 想定時間 |
|---|---|---|
| [2026-10-17-skill-plugin-development/](2026-10-17-skill-plugin-development/README.md) | 独自スキルプラグイン開発の薦め。NDF の機能を例に、自分用のスキルプラグインを作って育てることを薦める(社外の勉強会・登壇向け) | 30〜35分 / 23ページ |
| [2026-10-17-skill-plugin-development/](2026-10-17-skill-plugin-development/README.md) | 独自プラグイン開発の薦め。NDF の機能を例に、自分用のスキルを作り、プラグインにして配り、育てることを薦める(社外の勉強会・登壇向け) | 30〜35分 / 21ページ |
| [2026-08-06-ai-plugins-intro.md](2026-08-06-ai-plugins-intro.md) | ai-plugins / NDF v5.0.0 の個別機能紹介。各スキルに何が書いてあり、何を重視しているかを扱う | 15分 / 15枚 |

`2026-10-17-skill-plugin-development` の成果物は Google Slides で、pptx は生成スクリプトから作り直せるためコミットしません。
Expand Down
18 changes: 18 additions & 0 deletions issues/issue-2065-design-decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,21 @@ Marp を残して経路の 1 つにする案は、編集できない成果物を
2 つを外し、生成スクリプトの経路だけが残る。設計文書の「構成要素」の値の集合の記述もこの決定に従って読む。

根拠: Value 1・Value 6・Value 8(MVV 版 2)

### 決定 14: 構成を聞き手に見せるため、章扉を台本のページを消費しないページにし、ページの文言を台本の文から起こさない

利用者の差し戻し(2026-10-18)。発表資料を Google Slides で見て「読みづらい。スライドらしい言葉遣いに改め、章扉を入れる」
「(内部用語の見出しが)意味が分からない」と指摘した。原因は 2 つある。各ページの文言が台本の文を縮めただけで長く、
聞き手の知らない内部の語が説明なしに残っていた。章扉が無く、構成が見えなかった。

- **章扉はスピーカーノートを持たず、台本の番号を進めない。** 枠組みの `section` は台本のページを消費せず、ページ数の
照合(I5)からも外れる。ページ番号は章扉も数える。台本は話す内容の正本で、章扉に読み上げは無いため、台本に章扉の
区切りを置くと、読み上げの無いページを台本に持つことになる
- **ページの文言は台本の文を縮めて載せない。** 1 ページ 1 メッセージにし、見出しはそのページの結論を短く、箱と表は
短い句か体言止めにする。聞き手が知らない内部の語は言い換えるか、ページの中で一言で説明する。規約は体裁設計
(`layout-slide.md`)と生成の手順(`form-slide.md`)に置き、体裁レビュー(`layout-review`)が聞き手の目で見る

章扉を台本の区切りとして持ち、ノートを空にする案は、台本に読み上げの無いページが混ざり、尺の計算と台本の番号が
章扉の数だけずれるため採らない。

根拠: Value 6・Value 8(MVV 版 2)
7 changes: 4 additions & 3 deletions issues/issue-2065-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
| I2 | 資料 | トーン&マナーの差し替えは `slides/theme.json` だけで済み、枠組みのファイル(`slides/lib/`)を書き換えない。枠組みを写し直してもプロジェクトの値が残る | 枠組みを書き換えた資料は、汎用テンプレートの更新を取り込めない。書き換えかどうかは、資料の `slides/lib/` の内容のハッシュを、写した時点の `lib/` の内容のハッシュ(資料の `README.md` に書いた値)と比べて決め、一致しなければ書き換えとみなしてプロジェクトの値を `theme.json` へ移す。NDF の版は基準にしない(版はスプリント単位でしか上がらず、同じ版数のまま develop で `lib/` が変わるため、版では写した元の `lib/` を一意に指せない)。新しい汎用テンプレートの `lib/` を写し直すのは更新の取り込みであり、書き換えとはみなさない。取り込んだら `README.md` のハッシュを写し直した `lib/` の値へ書き換える |
| I3 | 資料 | 生成スクリプトと枠組みの関数の本体に、書体名と色の値を直接書かない。色は `theme.json` の項目名で指す | 直書きが残ると、差し替えた後も既定の値が pptx に残る。テストが落とす |
| I4 | 資料 | スピーカーノートは台本のファイルの読み上げから入れる。生成スクリプトに読み上げを写さない | 写すと台本と食い違う。枠組みが台本を読み込み、ページ番号で対応させる |
| I5 | 資料 | 生成した pptx のページ数は、台本のページ数と等しい | 生成スクリプトが終了コード 1 で止まり、両方の数を出す |
| I5 | 資料 | 生成した pptx のページ数から章扉を除いた数は、台本のページ数と等しい。章扉はスピーカーノートを持たず、台本の番号を進めない(決定 14) | 生成スクリプトが終了コード 1 で止まり、台本のページ数と、章扉を除いて作ったページ数と、章扉の数を出す |
| I6 | 資料 | 尺は台本の読み上げの字数を 350 字/分で割った値で、合計はページごとの値の和に等しい | 尺の上限(引数)を超えたら終了コード 1 を返し、構成メモで削るページを決める |
| I7 | 汎用テンプレート・資料 | 汎用テンプレートと資料に、手本の社名・案件名・コーポレートカラーの値・ロゴを入れない | 完了判定で差分の追加行を検索し、1 件でもあれば直す(受け入れ条件 13) |

Expand Down Expand Up @@ -340,6 +340,7 @@ classDiagram
| 読み上げ | 区切りの中の `>` で始まる行。`>` だけの行は段落の区切り。スピーカーノートは読み上げの段落を改行でつないだ文 |
| ほかの行 | ページに載せる要素の覚え書き。ノートにも字数にも入れない |
| 最初の区切りより前 | 題・想定・構成の表。読まない |
| 章扉 | 台本に区切りを置かない。生成スクリプトの `section` が作り、ノートを持たず、台本の番号を進めない(決定 14) |
| 失敗 | 区切りが 1 つも無い・番号が欠ける・重なる → 終了コード 2 と、どの番号かを出す |

### 構成メモ(`notes.md`)
Expand Down Expand Up @@ -407,7 +408,7 @@ sequenceDiagram

## 決定の記録

決定の記録は [issue-2065-design-decisions.md](issue-2065-design-decisions.md) にある(決定 1〜13。決定 3 は決定 12・13 が置き換えた)。
決定の記録は [issue-2065-design-decisions.md](issue-2065-design-decisions.md) にある(決定 1〜14。決定 3 は決定 12・13 が置き換えた)。

## テスト設計

Expand All @@ -420,7 +421,7 @@ sequenceDiagram
| 受け入れ条件 5・I2・I3 | 書体・色・著作権表示・ロゴを差し替えた `theme.json` で生成すると、全ページの XML の書体名と色が差し替えた値だけになり、既定値が残らない。`lib/` を写し直しても同じ結果になる | 枠組みか見本に書体名・色を直書きすると落ちる。`theme.json` の項目を重ねずに丸ごと置き換えると、書いていない既定値が欠けて落ちる |
| `theme.json` の知らない項目 | 知らない項目名を書くと終了コード 1 で、項目名を出す | 知らない項目を読み捨てると落ちる |
| I4・受け入れ条件 11 | 発表資料を生成すると 23 ページすべてにノートがあり、各ノートが `script.md` の同じ番号の読み上げと一致する | ノートを生成スクリプトに写して食い違わせる・番号をずらすと落ちる |
| I5 | 台本のページ数と作ったページ数が違うと、生成が終了コード 1 で両方の数を出す | 照合を外すと落ちる |
| I5 | 台本のページ数と、章扉を除いて作ったページ数が違うと、生成が終了コード 1 で両方の数と章扉の数を出す。章扉はノートを持たず、章扉の後のページは台本の次の番号の読み上げを受ける。発表資料は章扉を除く 23 ページが台本と一致する | 照合を外す・章扉で台本の番号を進める・章扉にノートを付けると落ちる |
| 台本の形の失敗 | 区切りの番号が欠ける・重なる台本で、生成と尺の計算が終了コード 2 と番号を出す | 欠けた番号を読み飛ばすと落ちる |
| I6・受け入れ条件 7 | 読み上げの字数が分かっている台本で、ページごとの字数と秒(350 字/分)と合計が期待どおりで、合計がページの和に等しい。`--limit` を下回る値にすると終了コード 1 | 空白や強調の記号を字数に数える・`>` 以外の行を数えると落ちる |
| 受け入れ条件 6 | 発表資料の `notes.md` の構成の表が 23 行で、番号が 1〜23(`tests/test_presentation_decks.py` が表を数える) | 行を欠かすと落ちる |
Expand Down
4 changes: 3 additions & 1 deletion plugins/ndf/skills/design/references/layout-slide.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
| 書体 | 見出しと本文。**配布先の環境にある書体か**を確かめる |
| 文字の大きさ | 見出し / 本文 / 注釈の 3 種類 |
| 色 | 地・文字・強調の 3 つ。**強調は 1 色に絞る** |
| 1 枚あたりの情報量 | **1 枚 1 主張。** 行数と図の数の上限 |
| 1 ページあたりの情報量 | **1 ページ 1 メッセージ。** 行数と図の数の上限 |
| ページの文言 | **台本の文を縮めて載せない。** 見出しはそのページの結論を短く、箱・表・箇条書きは短い句か体言止めにする。聞き手が知らない内部の語は、聞き手に通じる語へ言い換えるか、ページの中で一言で説明を添える |
| 章立て | **章扉で構成を見せる。** 章の名前と一言を決める。章扉はスピーカーノートを持たず、台本のページを消費しない |
| 図表の種類 | 使う図の種類と、使わない種類 |
| トーン&マナー | 上の書体・色・文字の大きさに、著作権表示の文言とロゴの有無を加えた組。**既定は会社色を持たない汎用テンプレートの値**で、変える項目だけを決める |
| ページの枠組み | 見出し・罫線・ロゴ・著作権表示・ページ番号・注の位置。**汎用テンプレートの枠組みの座標を使い、資料ごとに決め直さない** |
Expand Down
5 changes: 3 additions & 2 deletions plugins/ndf/skills/layout-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ allowed-tools:
| --- | --- |
| 事実・数値・出典・表現・構成 | コードレビュー(`cross-review`)と完了判定の事実確認 |
| 生成物と正本の内容の一致 | リリースの工程の内容照合(`document-systems` の `import.md`) |
| **版面**(文字あふれ・図の重なり・改ページ・書体) | **この Skill** |
| **版面**(文字あふれ・図の重なり・改ページ・書体・聞き手の目で文言が読めるか) | **この Skill** |

**重なる観点を持たない。** 版面の指摘と内容の指摘が混ざると、どちらの工程へ戻すのかが
決まらない。
Expand All @@ -41,7 +41,7 @@ allowed-tools:
| 見方 | 項目 |
| --- | --- |
| 機械で測る | 外部への参照が残っていないか / 図の横幅 / ページ数 / 1 枚あたりの文字数 |
| **人が画像を見る** | **枠からの文字あふれ / 図の重なり / 改ページの位置 / 書体の代替** |
| **人が画像を見る** | **枠からの文字あふれ / 図の重なり / 改ページの位置 / 書体の代替 / 聞き手の目で文言が読めるか(1 ページの文字量・文の長さ・説明の無い内部の語)** |

**機械で測るものを先に通す。** 落ちたらそこで生成へ戻す。画像を見るのはその後である。

Expand Down Expand Up @@ -93,6 +93,7 @@ allowed-tools:
| 原因 | 戻す先 |
| --- | --- |
| 版面の決め方(余白・文字の大きさ・1 枚あたりの情報量) | 体裁設計(`design` の `layout-<出力の形>.md`) |
| ページの文言(台本の文を縮めて載せた・説明の無い内部の語が残る) | 生成スクリプトのページの文言(`release` の `form-<出力の形>.md`) |
| 生成の経路(変換器の設定、指示の与え方、生成スクリプト) | リリースの生成の手順(`release` の `form-<出力の形>.md`) |
| 内容が多すぎて収まらない | **執筆へ戻す**(主張の数を減らす) |

Expand Down
5 changes: 3 additions & 2 deletions plugins/ndf/skills/release/assets/slides/build-deck.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// node build-deck.js <出力>.pptx [<theme.json>]
//
// 章扉は台本に区切りを置かない(台本は表紙と本編の 2 ページ)。
// 写した後はページの中身だけを書き換える。書体と色は theme.json で差し替え、ここに値を書かない。
// 色は theme.colors の項目名(accent・ink・panel1 など)で指す。
const path = require("path");
Expand All @@ -14,10 +15,10 @@ run(__dirname, { script: SCRIPT, title: "<資料の題>", author: "<作成者>"
// 1. 表紙
d.cover("<資料の題>", "<副題>", "<日付> <作成者>");

// 2. 章扉
// 章扉(台本の番号を進めず、ノートを持たない)
d.section("現状", "数値で見る前の期間との違い");

// 3. 本編(表と注)
// 2. 本編(表と注)
const s = d.page("現状の数値", "件数は増え、時間は短くなった。費用だけが増えた");
d.tbl(s, [
[d.H("指標"), d.H("前の期間"), d.H("今の期間"), d.H("差")],
Expand Down
Loading
Loading