@k2works/claude-code-booster 1.9.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,212 @@
1
1
  /**
2
- * HCOSS インセプションデッキ PowerPoint 生成スクリプト
2
+ * インセプションデッキ PowerPoint 生成スクリプト(汎用テンプレート)
3
3
  *
4
4
  * テンプレート: docs/template/インセプションデッキ.pptx のスライド構成に準拠
5
5
  * データソース: docs/analysis/inception-deck.md, docs/analysis/business_architecture.md
6
+ *
7
+ * 使い方:
8
+ * 1. SLIDE_DATA セクションのプレースホルダーをプロジェクト固有の内容に書き換える
9
+ * 2. node .claude/scripts/generate-inception-deck.mjs を実行
6
10
  */
7
11
  import PptxGenJS from "pptxgenjs";
8
12
  import { writeFileSync } from "fs";
9
13
  import { resolve } from "path";
10
14
 
11
- // ── テーマ設定(テンプレートから抽出) ──
15
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
16
+ // SLIDE_DATA: プロジェクト固有データ(ここを書き換える)
17
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
18
+ const SLIDE_DATA = {
19
+ // ── メタ情報 ──
20
+ meta: {
21
+ author: "プロジェクトチーム",
22
+ title: "プロジェクト名 インセプションデッキ",
23
+ version: "v0.1.0",
24
+ date: "YYYY-MM-DD",
25
+ outputFileName: "PROJECT_v0.1.0.pptx",
26
+ },
27
+
28
+ // ── Slide 1: タイトル ──
29
+ titleSlide: {
30
+ projectName: "プロジェクト名",
31
+ subtitle: "プロジェクトの説明",
32
+ deckLabel: "インセプションデッキ",
33
+ organization: "組織名",
34
+ },
35
+
36
+ // ── Slide 2: 我われはなぜここにいるのか ──
37
+ whyAreWeHere: {
38
+ subtitle: "プロジェクトが解決すべき課題の概要",
39
+ bullets: [
40
+ "課題 1: 現状の問題点を記述",
41
+ "課題 2: 現状の問題点を記述",
42
+ "課題 3: 現状の問題点を記述",
43
+ ],
44
+ highlight: "課題を一文で要約するメッセージ",
45
+ },
46
+
47
+ // ── Slide 3: エレベーターピッチ ──
48
+ elevatorPitch: {
49
+ want: "〇〇を実現",
50
+ targetUser: "ターゲットユーザーの説明",
51
+ productName: "プロダクト名",
52
+ category: "プロダクトカテゴリ",
53
+ keyBenefit: "主要な機能・利点の説明",
54
+ competitor: "既存の代替手段",
55
+ differentiator: "差別化ポイント",
56
+ },
57
+
58
+ // ── Slide 4: どんな価値をもたらすのか? ──
59
+ values: {
60
+ rows: [
61
+ // [番号, ビジネス目標, 期待される効果]
62
+ ["1", "ビジネス目標 1", "期待される効果 1"],
63
+ ["2", "ビジネス目標 2", "期待される効果 2"],
64
+ ["3", "ビジネス目標 3", "期待される効果 3"],
65
+ ],
66
+ },
67
+
68
+ // ── Slide 5: やらないことリスト ──
69
+ scope: {
70
+ inScope: [
71
+ "スコープ内の機能 1",
72
+ "スコープ内の機能 2",
73
+ "スコープ内の機能 3",
74
+ ],
75
+ outOfScope: [
76
+ "スコープ外の項目 1",
77
+ "スコープ外の項目 2",
78
+ ],
79
+ decideLater: [
80
+ "後で決める項目 1",
81
+ "後で決める項目 2",
82
+ ],
83
+ },
84
+
85
+ // ── Slide 6: プロジェクトコミュニティ ──
86
+ stakeholders: {
87
+ rows: [
88
+ // [ステークホルダー, 役割, 主な関心事]
89
+ ["ステークホルダー 1", "役割", "関心事"],
90
+ ["ステークホルダー 2", "役割", "関心事"],
91
+ ["ステークホルダー 3", "役割", "関心事"],
92
+ ],
93
+ },
94
+
95
+ // ── Slide 7: 技術的な解決策の概要 ──
96
+ technicalSolution: {
97
+ // 上部の外部チャネル(モール、外部 API など)
98
+ externalChannels: [
99
+ { name: "チャネル 1" },
100
+ { name: "チャネル 2" },
101
+ { name: "チャネル 3" },
102
+ ],
103
+ // 中央のシステム
104
+ systemName: "システム名",
105
+ modules: [
106
+ "モジュール 1",
107
+ "モジュール 2",
108
+ "モジュール 3",
109
+ "モジュール 4",
110
+ ],
111
+ // 下部の外部連携先
112
+ externalServices: [
113
+ { name: "外部サービス 1" },
114
+ { name: "外部サービス 2" },
115
+ { name: "外部サービス 3" },
116
+ ],
117
+ techNote: "技術方針の概要を一文で記述",
118
+ },
119
+
120
+ // ── Slide 8: 夜も眠れなくなるような問題 ──
121
+ risks: {
122
+ rows: [
123
+ // [番号, リスク, 影響度, 対策]
124
+ ["1", "リスク 1", "高", "対策 1"],
125
+ ["2", "リスク 2", "中", "対策 2"],
126
+ ["3", "リスク 3", "低", "対策 3"],
127
+ ],
128
+ },
129
+
130
+ // ── Slide 9: 俺たちの "A チーム" ──
131
+ team: {
132
+ rows: [
133
+ // [役割, 人数, 備考]
134
+ ["役割 1", "N 名", "備考"],
135
+ ["役割 2", "N 名", "備考"],
136
+ ],
137
+ highlight: "チーム体制の特徴やポイントを一文で記述",
138
+ },
139
+
140
+ // ── Slide 10: 期間を見極める ──
141
+ timeline: {
142
+ totalWeeks: 12,
143
+ phases: [
144
+ // weeks: ガントバー上の幅(週数)
145
+ {
146
+ name: "Phase 1: フェーズ名",
147
+ desc: "主な作業内容",
148
+ weeksLabel: "N 週間",
149
+ weeks: 3,
150
+ },
151
+ {
152
+ name: "Phase 2: フェーズ名",
153
+ desc: "主な作業内容",
154
+ weeksLabel: "N 週間",
155
+ weeks: 4,
156
+ },
157
+ {
158
+ name: "Phase 3: フェーズ名",
159
+ desc: "主な作業内容",
160
+ weeksLabel: "N 週間",
161
+ weeks: 3,
162
+ },
163
+ {
164
+ name: "Phase 4: フェーズ名",
165
+ desc: "主な作業内容",
166
+ weeksLabel: "N 週間",
167
+ weeks: 2,
168
+ },
169
+ ],
170
+ // MVP マーカーを表示するフェーズ番号(0 始まり。先頭から N フェーズ完了時点)
171
+ // null の場合はマーカーを表示しない
172
+ mvpAfterPhase: 1,
173
+ },
174
+
175
+ // ── Slide 11: トレードオフ・スライダー ──
176
+ tradeoffs: {
177
+ // level: 1=MIN 〜 4=MAX
178
+ sliders: [
179
+ { label: "機能をぜんぶ揃える(スコープ)", level: 2 },
180
+ { label: "予算内に収める(予算)", level: 2 },
181
+ { label: "期日を死守する(時間)", level: 2 },
182
+ { label: "高い品質、少ない欠陥(品質)", level: 3 },
183
+ ],
184
+ qualityPriorities: [
185
+ // [優先度, 品質特性, 理由]
186
+ ["1", "品質特性 1", "理由 1"],
187
+ ["2", "品質特性 2", "理由 2"],
188
+ ["3", "品質特性 3", "理由 3"],
189
+ ],
190
+ },
191
+
192
+ // ── Slide 12: 初回のリリースに必要なもの ──
193
+ initialRelease: {
194
+ highlight: "MVP の概要を一文で記述",
195
+ mvpScope: [
196
+ "MVP 機能 1",
197
+ "MVP 機能 2",
198
+ "MVP 機能 3",
199
+ ],
200
+ releaseStrategy: [
201
+ "リリース戦略 1",
202
+ "リリース戦略 2",
203
+ ],
204
+ },
205
+ };
206
+
207
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
208
+ // テーマ設定(テンプレートから抽出)
209
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
12
210
  const COLORS = {
13
211
  black: "000000",
14
212
  white: "FFFFFF",
@@ -30,16 +228,9 @@ const FONT = {
30
228
  code: "Courier New",
31
229
  };
32
230
 
33
- // ── ヘルパー ──
34
- function titleSlideOpts(title, subtitle) {
35
- return {
36
- color: COLORS.white,
37
- fontFace: FONT.title,
38
- bold: true,
39
- fontSize: subtitle ? 32 : 40,
40
- };
41
- }
42
-
231
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
232
+ // ヘルパー関数
233
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
43
234
  function addTitle(slide, text) {
44
235
  slide.addText(text, {
45
236
  x: 0.5,
@@ -142,7 +333,6 @@ function addHighlightBox(slide, text, opts = {}) {
142
333
  }
143
334
 
144
335
  function addSliderBar(slide, label, level, y) {
145
- // level: 1-4 (1=MIN, 4=MAX)
146
336
  const barX = 3.5;
147
337
  const barW = 5.0;
148
338
  const segW = barW / 4;
@@ -190,24 +380,27 @@ function addSliderBar(slide, label, level, y) {
190
380
  });
191
381
  }
192
382
 
193
- // ── メイン ──
383
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
384
+ // スライド生成
385
+ // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
194
386
  async function main() {
387
+ const { meta } = SLIDE_DATA;
388
+
195
389
  const pptx = new PptxGenJS();
196
390
  pptx.defineLayout({ name: "SCREEN_4x3", width: 10, height: 7.5 });
197
391
  pptx.layout = "SCREEN_4x3";
198
- pptx.author = "HCOSS Project";
199
- pptx.title = "HCOSS インセプションデッキ v0.1.0";
392
+ pptx.author = meta.author;
393
+ pptx.title = meta.title;
200
394
 
201
- // ───────────────────────────────────────
202
- // Slide 1: タイトル
203
- // ───────────────────────────────────────
395
+ // ─── Slide 1: タイトル ───
204
396
  {
397
+ const d = SLIDE_DATA.titleSlide;
205
398
  const slide = pptx.addSlide();
206
399
  slide.background = { color: COLORS.darkBlue };
207
400
  slide.addText(
208
401
  [
209
402
  {
210
- text: "HCOSS",
403
+ text: d.projectName,
211
404
  options: {
212
405
  fontSize: 48,
213
406
  fontFace: FONT.title,
@@ -217,7 +410,7 @@ async function main() {
217
410
  },
218
411
  },
219
412
  {
220
- text: "統合業務管理システム",
413
+ text: d.subtitle,
221
414
  options: {
222
415
  fontSize: 28,
223
416
  fontFace: FONT.title,
@@ -226,7 +419,7 @@ async function main() {
226
419
  },
227
420
  },
228
421
  {
229
- text: "インセプションデッキ",
422
+ text: d.deckLabel,
230
423
  options: {
231
424
  fontSize: 24,
232
425
  fontFace: FONT.title,
@@ -237,7 +430,7 @@ async function main() {
237
430
  ],
238
431
  { x: 1.0, y: 1.5, w: 8.0, h: 3.5, align: "center", valign: "middle" }
239
432
  );
240
- slide.addText("ヘルシーカンパニー株式会社", {
433
+ slide.addText(d.organization, {
241
434
  x: 1.0,
242
435
  y: 5.5,
243
436
  w: 8.0,
@@ -247,7 +440,7 @@ async function main() {
247
440
  color: COLORS.lightTeal,
248
441
  align: "center",
249
442
  });
250
- slide.addText("v0.1.0 | 2026-02-27", {
443
+ slide.addText(`${meta.version} | ${meta.date}`, {
251
444
  x: 1.0,
252
445
  y: 6.2,
253
446
  w: 8.0,
@@ -259,130 +452,53 @@ async function main() {
259
452
  });
260
453
  }
261
454
 
262
- // ───────────────────────────────────────
263
- // Slide 2: 我われはなぜここにいるのか
264
- // ───────────────────────────────────────
455
+ // ─── Slide 2: 我われはなぜここにいるのか ───
265
456
  {
457
+ const d = SLIDE_DATA.whyAreWeHere;
266
458
  const slide = pptx.addSlide();
267
459
  addTitle(slide, "我われはなぜここにいるのか");
268
- addSubtitle(
269
- slide,
270
- "正社員 6 名・パート 10 名の小規模体制で 4 つのショッピングモールを運営する課題"
271
- );
272
- addBullets(slide, [
273
- "受注管理の分散:4 モールからの受注データが統合されておらず、個別処理の非効率が発生",
274
- "在庫管理の複雑性:自社在庫と Amazon FBA 在庫の二元管理が手作業中心",
275
- "データ分析の不在:売上・顧客データの分析基盤がなく、データに基づく意思決定ができていない",
276
- "マーケティング戦略の未整備:効果的なマーケティング施策を立案・実行できていない",
277
- "コーポレートサイトの活用不足:企業情報・製造所情報の発信が不十分",
278
- ]);
279
-
280
- addHighlightBox(slide, "小規模組織の手作業の限界が、業務の品質と効率を圧迫している", {
460
+ addSubtitle(slide, d.subtitle);
461
+ addBullets(slide, d.bullets);
462
+ addHighlightBox(slide, d.highlight, {
281
463
  y: 5.8,
282
464
  h: 0.7,
283
465
  fontSize: 14,
284
466
  });
285
467
  }
286
468
 
287
- // ───────────────────────────────────────
288
- // Slide 3: エレベーターピッチ
289
- // ───────────────────────────────────────
469
+ // ─── Slide 3: エレベーターピッチ ───
290
470
  {
471
+ const d = SLIDE_DATA.elevatorPitch;
291
472
  const slide = pptx.addSlide();
292
473
  addTitle(slide, "エレベーターピッチ");
293
474
 
475
+ const bold = {
476
+ fontSize: 14,
477
+ fontFace: FONT.body,
478
+ color: COLORS.darkBlue,
479
+ bold: true,
480
+ };
481
+ const normal = {
482
+ fontSize: 14,
483
+ fontFace: FONT.body,
484
+ color: COLORS.black,
485
+ };
486
+
294
487
  const pitchParts = [
295
- {
296
- text: "マルチモール運営を効率化",
297
- options: {
298
- fontSize: 14,
299
- fontFace: FONT.body,
300
- color: COLORS.darkBlue,
301
- bold: true,
302
- },
303
- },
304
- {
305
- text: " したい\n",
306
- options: { fontSize: 14, fontFace: FONT.body, color: COLORS.black },
307
- },
308
- {
309
- text: "正社員 6 名・パート 10 名の小規模食品加工業者",
310
- options: {
311
- fontSize: 14,
312
- fontFace: FONT.body,
313
- color: COLORS.darkBlue,
314
- bold: true,
315
- },
316
- },
317
- {
318
- text: " 向けの、\n",
319
- options: { fontSize: 14, fontFace: FONT.body, color: COLORS.black },
320
- },
321
- {
322
- text: "HCOSS(統合業務管理システム)",
323
- options: {
324
- fontSize: 14,
325
- fontFace: FONT.body,
326
- color: COLORS.darkBlue,
327
- bold: true,
328
- },
329
- },
330
- {
331
- text: " というプロダクトは、\n",
332
- options: { fontSize: 14, fontFace: FONT.body, color: COLORS.black },
333
- },
334
- {
335
- text: "マルチモール統合業務管理システム",
336
- options: {
337
- fontSize: 14,
338
- fontFace: FONT.body,
339
- color: COLORS.darkBlue,
340
- bold: true,
341
- },
342
- },
343
- {
344
- text: " です。\nこれは ",
345
- options: { fontSize: 14, fontFace: FONT.body, color: COLORS.black },
346
- },
347
- {
348
- text: "4 モールの受注・在庫・出荷を統合管理し、\n食品トレーサビリティを一貫して管理",
349
- options: {
350
- fontSize: 14,
351
- fontFace: FONT.body,
352
- color: COLORS.darkBlue,
353
- bold: true,
354
- },
355
- },
356
- {
357
- text: " ができ、\n",
358
- options: { fontSize: 14, fontFace: FONT.body, color: COLORS.black },
359
- },
360
- {
361
- text: "各モール個別の手作業管理",
362
- options: {
363
- fontSize: 14,
364
- fontFace: FONT.body,
365
- color: COLORS.darkBlue,
366
- bold: true,
367
- },
368
- },
369
- {
370
- text: " とは違って、\n",
371
- options: { fontSize: 14, fontFace: FONT.body, color: COLORS.black },
372
- },
373
- {
374
- text: "シンプルで運用負荷の低い統合基盤",
375
- options: {
376
- fontSize: 14,
377
- fontFace: FONT.body,
378
- color: COLORS.darkBlue,
379
- bold: true,
380
- },
381
- },
382
- {
383
- text: " が備わっている。",
384
- options: { fontSize: 14, fontFace: FONT.body, color: COLORS.black },
385
- },
488
+ { text: d.want, options: bold },
489
+ { text: " したい\n", options: normal },
490
+ { text: d.targetUser, options: bold },
491
+ { text: " 向けの、\n", options: normal },
492
+ { text: d.productName, options: bold },
493
+ { text: " というプロダクトは、\n", options: normal },
494
+ { text: d.category, options: bold },
495
+ { text: " です。\nこれは ", options: normal },
496
+ { text: d.keyBenefit, options: bold },
497
+ { text: " ができ、\n", options: normal },
498
+ { text: d.competitor, options: bold },
499
+ { text: " とは違って、\n", options: normal },
500
+ { text: d.differentiator, options: bold },
501
+ { text: " が備わっている。", options: normal },
386
502
  ];
387
503
 
388
504
  slide.addText(pitchParts, {
@@ -396,92 +512,32 @@ async function main() {
396
512
  });
397
513
  }
398
514
 
399
- // ───────────────────────────────────────
400
- // Slide 4: どんな価値をもたらすのか?
401
- // ───────────────────────────────────────
515
+ // ─── Slide 4: どんな価値をもたらすのか? ───
402
516
  {
517
+ const d = SLIDE_DATA.values;
403
518
  const slide = pptx.addSlide();
404
519
  addTitle(slide, "どんな価値をもたらすのか?");
405
520
  addTable(
406
521
  slide,
407
522
  ["#", "ビジネス目標", "期待される効果"],
408
- [
409
- ["1", "マルチモール受注の統合管理", "4 モールの受注を一元管理し、処理時間を短縮"],
410
- [
411
- "2",
412
- "在庫の統合管理",
413
- "自社在庫と FBA 在庫を統合管理し、在庫切れ・過剰在庫を防止",
414
- ],
415
- [
416
- "3",
417
- "トレーサビリティの確保",
418
- "原材料から出荷までの追跡で食品安全基準への対応を強化",
419
- ],
420
- [
421
- "4",
422
- "データに基づく意思決定",
423
- "売上・顧客データの分析基盤を構築しマーケティング戦略を立案可能に",
424
- ],
425
- [
426
- "5",
427
- "業務効率の向上",
428
- "手作業を削減し、小規模体制でも持続可能な業務運営を実現",
429
- ],
430
- [
431
- "6",
432
- "顧客満足度の向上",
433
- "迅速かつ正確な受注・出荷処理により顧客体験を改善",
434
- ],
435
- ],
523
+ d.rows,
436
524
  { colW: [0.4, 3.0, 5.6] }
437
525
  );
438
526
  }
439
527
 
440
- // ───────────────────────────────────────
441
- // Slide 5: やらないことリスト(スコープ)
442
- // ───────────────────────────────────────
528
+ // ─── Slide 5: やらないことリスト ───
443
529
  {
530
+ const d = SLIDE_DATA.scope;
444
531
  const slide = pptx.addSlide();
445
532
  addTitle(slide, "やらないことリスト");
446
533
  addSubtitle(slide, "スコープの範囲");
447
534
 
448
- // Three columns
449
535
  const colW = 2.85;
450
536
  const colGap = 0.15;
451
537
  const cols = [
452
- {
453
- title: "やる(スコープ内)",
454
- color: COLORS.teal,
455
- items: [
456
- "マルチモール受注管理",
457
- "在庫管理(自社 + FBA)",
458
- "出荷管理",
459
- "商品管理",
460
- "品質管理・トレーサビリティ",
461
- "調達管理",
462
- "売上・顧客データ分析",
463
- "カスタマーサポート管理",
464
- ],
465
- },
466
- {
467
- title: "やらない(スコープ外)",
468
- color: COLORS.red,
469
- items: [
470
- "財務・会計管理",
471
- "人事・労務管理",
472
- "コーポレートサイトの構築",
473
- "モール API 以外の外部連携",
474
- ],
475
- },
476
- {
477
- title: "あとで決める",
478
- color: COLORS.orange,
479
- items: [
480
- "外部製造委託管理の範囲",
481
- "製造所固有記号管理",
482
- "マーケティング自動化",
483
- ],
484
- },
538
+ { title: "やる(スコープ内)", color: COLORS.teal, items: d.inScope },
539
+ { title: "やらない(スコープ外)", color: COLORS.red, items: d.outOfScope },
540
+ { title: "あとで決める", color: COLORS.orange, items: d.decideLater },
485
541
  ];
486
542
 
487
543
  cols.forEach((col, i) => {
@@ -519,78 +575,46 @@ async function main() {
519
575
  });
520
576
  }
521
577
 
522
- // ───────────────────────────────────────
523
- // Slide 6: 主なステークホルダー
524
- // ───────────────────────────────────────
578
+ // ─── Slide 6: プロジェクトコミュニティ ───
525
579
  {
580
+ const d = SLIDE_DATA.stakeholders;
526
581
  const slide = pptx.addSlide();
527
582
  addTitle(slide, "プロジェクトコミュニティ");
528
583
  addSubtitle(slide, "主なステークホルダーと関心事");
529
584
  addTable(
530
585
  slide,
531
586
  ["ステークホルダー", "役割", "主な関心事"],
532
- [
533
- [
534
- "経営者",
535
- "プロジェクトオーナー",
536
- "投資対効果、業務効率化、売上向上",
537
- ],
538
- [
539
- "販売部門",
540
- "主要ユーザー",
541
- "受注・出荷業務の効率化、在庫可視化",
542
- ],
543
- [
544
- "製造部門",
545
- "ユーザー",
546
- "在庫引当の正確性、品質管理の効率化",
547
- ],
548
- ["顧客", "エンドユーザー", "正確な在庫情報、迅速な配送"],
549
- [
550
- "提携製造所",
551
- "外部パートナー",
552
- "製造指示の明確化、納品プロセスの効率化",
553
- ],
554
- [
555
- "モール運営会社",
556
- "プラットフォーム",
557
- "API 連携の安定性、商品情報の正確性",
558
- ],
559
- [
560
- "配送業者",
561
- "外部パートナー",
562
- "出荷情報の正確性、集荷スケジュールの安定",
563
- ],
564
- ],
587
+ d.rows,
565
588
  { y: 1.7, colW: [2.0, 2.2, 4.8] }
566
589
  );
567
590
  }
568
591
 
569
- // ───────────────────────────────────────
570
- // Slide 7: 技術的な解決策の概要
571
- // ───────────────────────────────────────
592
+ // ─── Slide 7: 技術的な解決策の概要 ───
572
593
  {
594
+ const d = SLIDE_DATA.technicalSolution;
573
595
  const slide = pptx.addSlide();
574
596
  addTitle(slide, "技術的な解決策の概要");
575
597
 
576
- // Architecture diagram using shapes
577
598
  const boxH = 0.5;
578
599
 
579
- // Mall boxes at top
580
- const malls = ["楽天市場", "Yahoo!", "Amazon", "au PAY"];
581
- malls.forEach((name, i) => {
600
+ // 上部: 外部チャネル
601
+ const channelCount = d.externalChannels.length;
602
+ const channelW = Math.min(2.0, (9.0 - 0.2 * (channelCount - 1)) / channelCount);
603
+ const channelGap = channelCount > 1 ? (9.0 - channelW * channelCount) / (channelCount - 1) : 0;
604
+ d.externalChannels.forEach((ch, i) => {
605
+ const x = 0.5 + i * (channelW + channelGap);
582
606
  slide.addShape("rect", {
583
- x: 0.5 + i * 2.2,
607
+ x,
584
608
  y: 1.5,
585
- w: 2.0,
609
+ w: channelW,
586
610
  h: boxH,
587
611
  fill: { color: COLORS.lightTeal },
588
612
  line: { color: COLORS.teal, width: 1 },
589
613
  });
590
- slide.addText(name, {
591
- x: 0.5 + i * 2.2,
614
+ slide.addText(ch.name, {
615
+ x,
592
616
  y: 1.5,
593
- w: 2.0,
617
+ w: channelW,
594
618
  h: boxH,
595
619
  fontSize: 10,
596
620
  fontFace: FONT.body,
@@ -600,7 +624,7 @@ async function main() {
600
624
  });
601
625
  });
602
626
 
603
- // Arrow label
627
+ // 接続ラベル
604
628
  slide.addText("API", {
605
629
  x: 4.0,
606
630
  y: 2.05,
@@ -612,7 +636,7 @@ async function main() {
612
636
  align: "center",
613
637
  });
614
638
 
615
- // HCOSS main box
639
+ // 中央: メインシステム
616
640
  slide.addShape("rect", {
617
641
  x: 0.5,
618
642
  y: 2.5,
@@ -621,7 +645,7 @@ async function main() {
621
645
  fill: { color: "F8F8FF" },
622
646
  line: { color: COLORS.darkBlue, width: 2 },
623
647
  });
624
- slide.addText("HCOSS 統合業務管理システム", {
648
+ slide.addText(d.systemName, {
625
649
  x: 0.5,
626
650
  y: 2.5,
627
651
  w: 9.0,
@@ -633,17 +657,8 @@ async function main() {
633
657
  align: "center",
634
658
  });
635
659
 
636
- // Internal modules
637
- const modules = [
638
- "受注管理",
639
- "在庫管理",
640
- "出荷管理",
641
- "商品管理",
642
- "品質管理",
643
- "調達管理",
644
- "分析",
645
- ];
646
- modules.forEach((name, i) => {
660
+ // 内部モジュール
661
+ d.modules.forEach((name, i) => {
647
662
  const row = Math.floor(i / 4);
648
663
  const col = i % 4;
649
664
  slide.addShape("roundRect", {
@@ -667,26 +682,24 @@ async function main() {
667
682
  });
668
683
  });
669
684
 
670
- // External services at bottom
671
- const extServices = [
672
- { name: "Amazon FBA", x: 0.5 },
673
- { name: "配送業者", x: 3.0 },
674
- { name: "自社工場", x: 5.5 },
675
- { name: "提携製造所", x: 7.5 },
676
- ];
677
- extServices.forEach((svc) => {
685
+ // 下部: 外部連携先
686
+ const svcCount = d.externalServices.length;
687
+ const svcW = Math.min(2.0, (9.0 - 0.2 * (svcCount - 1)) / svcCount);
688
+ const svcGap = svcCount > 1 ? (9.0 - svcW * svcCount) / (svcCount - 1) : 0;
689
+ d.externalServices.forEach((svc, i) => {
690
+ const x = 0.5 + i * (svcW + svcGap);
678
691
  slide.addShape("rect", {
679
- x: svc.x,
692
+ x,
680
693
  y: 5.6,
681
- w: 2.0,
694
+ w: svcW,
682
695
  h: boxH,
683
696
  fill: { color: "FFF3E0" },
684
697
  line: { color: COLORS.orange, width: 1 },
685
698
  });
686
699
  slide.addText(svc.name, {
687
- x: svc.x,
700
+ x,
688
701
  y: 5.6,
689
- w: 2.0,
702
+ w: svcW,
690
703
  h: boxH,
691
704
  fontSize: 10,
692
705
  fontFace: FONT.body,
@@ -696,8 +709,8 @@ async function main() {
696
709
  });
697
710
  });
698
711
 
699
- // Tech stack note
700
- slide.addText("技術方針: シンプルで運用負荷の低いシステム / マルチモール統合基盤 / トレーサビリティ対応", {
712
+ // 技術方針ノート
713
+ slide.addText(d.techNote, {
701
714
  x: 0.5,
702
715
  y: 6.4,
703
716
  w: 9.0,
@@ -709,142 +722,56 @@ async function main() {
709
722
  });
710
723
  }
711
724
 
712
- // ───────────────────────────────────────
713
- // Slide 8: 夜も眠れなくなるような問題
714
- // ───────────────────────────────────────
725
+ // ─── Slide 8: 夜も眠れなくなるような問題 ───
715
726
  {
727
+ const d = SLIDE_DATA.risks;
716
728
  const slide = pptx.addSlide();
717
729
  addTitle(slide, "夜も眠れなくなるような問題は何だろう?");
718
730
  addTable(
719
731
  slide,
720
732
  ["#", "リスク", "影響度", "対策"],
721
- [
722
- [
723
- "1",
724
- "モール API の変更・制約",
725
- "高",
726
- "アダプタパターンによる API 変更への対応力確保",
727
- ],
728
- [
729
- "2",
730
- "小規模チームでの開発・運用リソース不足",
731
- "高",
732
- "シンプルな設計を最優先。段階的リリース",
733
- ],
734
- [
735
- "3",
736
- "FBA 在庫と自社在庫の同期ズレ",
737
- "中",
738
- "Amazon API での定期的な在庫同期。差異検知アラート",
739
- ],
740
- [
741
- "4",
742
- "既存業務プロセスとの不整合",
743
- "中",
744
- "現場ヒアリングの徹底。段階的な業務移行",
745
- ],
746
- [
747
- "5",
748
- "食品安全・法令遵守の不備",
749
- "高",
750
- "食品衛生法の要件を設計段階から組み込む",
751
- ],
752
- [
753
- "6",
754
- "データ移行の失敗",
755
- "中",
756
- "段階的な移行計画。並行稼動期間の確保",
757
- ],
758
- ],
733
+ d.rows,
759
734
  { colW: [0.4, 3.0, 0.8, 4.8] }
760
735
  );
761
736
  }
762
737
 
763
- // ───────────────────────────────────────
764
- // Slide 9: 俺たちの "A チーム"
765
- // ───────────────────────────────────────
738
+ // ─── Slide 9: 俺たちの "A チーム" ───
766
739
  {
740
+ const d = SLIDE_DATA.team;
767
741
  const slide = pptx.addSlide();
768
742
  addTitle(slide, '俺たちの "A チーム"');
769
743
  addTable(
770
744
  slide,
771
745
  ["役割", "人数", "備考"],
772
- [
773
- ["プロジェクトオーナー", "1 名", "経営者が兼務"],
774
- ["開発者", "1〜2 名", "AI エージェントとの協働開発"],
775
- [
776
- "業務担当(販売・製造)",
777
- "2〜3 名",
778
- "要件確認・受入テスト",
779
- ],
780
- ],
746
+ d.rows,
781
747
  { y: 1.8, colW: [2.5, 1.5, 5.0] }
782
748
  );
783
-
784
- addHighlightBox(
785
- slide,
786
- "AI エージェント(Claude Code)との協働開発により、少人数でも高品質な開発を実現",
787
- { y: 4.0, h: 0.8, fontSize: 14 }
788
- );
749
+ addHighlightBox(slide, d.highlight, { y: 4.0, h: 0.8, fontSize: 14 });
789
750
  }
790
751
 
791
- // ───────────────────────────────────────
792
- // Slide 10: 期間を見極める
793
- // ───────────────────────────────────────
752
+ // ─── Slide 10: 期間を見極める ───
794
753
  {
754
+ const d = SLIDE_DATA.timeline;
795
755
  const slide = pptx.addSlide();
796
756
  addTitle(slide, "期間を見極める");
797
757
 
798
- const phases = [
799
- {
800
- name: "Phase 1: 分析・設計",
801
- desc: "要件定義、アーキテクチャ設計、データモデル設計",
802
- weeks: "2〜3 週間",
803
- color: COLORS.lightTeal,
804
- },
805
- {
806
- name: "Phase 2: コア機能開発",
807
- desc: "受注管理、在庫管理、出荷管理、商品管理",
808
- weeks: "4〜6 週間",
809
- color: COLORS.teal,
810
- },
811
- {
812
- name: "Phase 3: 品質管理・調達管理",
813
- desc: "品質管理、調達管理機能の開発",
814
- weeks: "2〜3 週間",
815
- color: COLORS.lightTeal,
816
- },
817
- {
818
- name: "Phase 4: 分析・サポート",
819
- desc: "分析ダッシュボード、カスタマーサポート",
820
- weeks: "2〜3 週間",
821
- color: COLORS.teal,
822
- },
823
- {
824
- name: "Phase 5: リリース準備",
825
- desc: "受入テスト、データ移行、本番稼動",
826
- weeks: "2〜3 週間",
827
- color: COLORS.lightTeal,
828
- },
829
- ];
830
-
831
758
  const barStartX = 0.5;
832
759
  const barMaxW = 9.0;
833
- const totalWeeks = 18;
834
- const phaseWeeks = [3, 6, 3, 3, 3];
760
+ const phaseWeeks = d.phases.map((p) => p.weeks);
835
761
 
836
- phases.forEach((phase, i) => {
762
+ d.phases.forEach((phase, i) => {
837
763
  const y = 1.8 + i * 1.0;
838
764
  const startWeek = phaseWeeks.slice(0, i).reduce((a, b) => a + b, 0);
839
- const x = barStartX + (startWeek / totalWeeks) * barMaxW;
840
- const w = (phaseWeeks[i] / totalWeeks) * barMaxW;
765
+ const x = barStartX + (startWeek / d.totalWeeks) * barMaxW;
766
+ const w = (phaseWeeks[i] / d.totalWeeks) * barMaxW;
767
+ const fillColor = i % 2 === 0 ? COLORS.lightTeal : COLORS.teal;
841
768
 
842
769
  slide.addShape("rect", {
843
770
  x,
844
771
  y,
845
772
  w,
846
773
  h: 0.45,
847
- fill: { color: phase.color },
774
+ fill: { color: fillColor },
848
775
  line: { color: COLORS.teal, width: 1 },
849
776
  });
850
777
  slide.addText(phase.name, {
@@ -859,7 +786,7 @@ async function main() {
859
786
  align: "center",
860
787
  valign: "middle",
861
788
  });
862
- slide.addText(`${phase.desc}(${phase.weeks})`, {
789
+ slide.addText(`${phase.desc}(${phase.weeksLabel})`, {
863
790
  x,
864
791
  y: y + 0.45,
865
792
  w,
@@ -871,28 +798,31 @@ async function main() {
871
798
  });
872
799
  });
873
800
 
874
- // MVP marker
875
- const mvpX =
876
- barStartX +
877
- ((phaseWeeks[0] + phaseWeeks[1]) / totalWeeks) * barMaxW;
878
- slide.addShape("line", {
879
- x: mvpX,
880
- y: 1.5,
881
- w: 0,
882
- h: 5.0,
883
- line: { color: COLORS.red, width: 2, dashType: "dash" },
884
- });
885
- slide.addText("MVP\nリリース", {
886
- x: mvpX - 0.5,
887
- y: 6.5,
888
- w: 1.2,
889
- h: 0.5,
890
- fontSize: 10,
891
- fontFace: FONT.body,
892
- bold: true,
893
- color: COLORS.red,
894
- align: "center",
895
- });
801
+ // MVP マーカー
802
+ if (d.mvpAfterPhase != null) {
803
+ const mvpWeeks = phaseWeeks
804
+ .slice(0, d.mvpAfterPhase + 1)
805
+ .reduce((a, b) => a + b, 0);
806
+ const mvpX = barStartX + (mvpWeeks / d.totalWeeks) * barMaxW;
807
+ slide.addShape("line", {
808
+ x: mvpX,
809
+ y: 1.5,
810
+ w: 0,
811
+ h: 5.0,
812
+ line: { color: COLORS.red, width: 2, dashType: "dash" },
813
+ });
814
+ slide.addText("MVP\nリリース", {
815
+ x: mvpX - 0.5,
816
+ y: 6.5,
817
+ w: 1.2,
818
+ h: 0.5,
819
+ fontSize: 10,
820
+ fontFace: FONT.body,
821
+ bold: true,
822
+ color: COLORS.red,
823
+ align: "center",
824
+ });
825
+ }
896
826
 
897
827
  slide.addText("あくまで推測であって、確約するものではありません。", {
898
828
  x: 0.5,
@@ -906,33 +836,20 @@ async function main() {
906
836
  });
907
837
  }
908
838
 
909
- // ───────────────────────────────────────
910
- // Slide 11: トレードオフ・スライダー
911
- // ───────────────────────────────────────
839
+ // ─── Slide 11: トレードオフ・スライダー ───
912
840
  {
841
+ const d = SLIDE_DATA.tradeoffs;
913
842
  const slide = pptx.addSlide();
914
843
  addTitle(slide, "トレードオフ・スライダー");
915
844
 
916
- // labels and levels (1=MIN..4=MAX)
917
- addSliderBar(
918
- slide,
919
- "機能をぜんぶ揃える(スコープ)",
920
- 3,
921
- 1.8
922
- );
923
- addSliderBar(slide, "予算内に収める(予算)", 2, 2.5);
924
- addSliderBar(slide, "期日を死守する(時間)", 2, 3.2);
925
- addSliderBar(
926
- slide,
927
- "高い品質、少ない欠陥(品質)",
928
- 4,
929
- 3.9
930
- );
845
+ d.sliders.forEach((s, i) => {
846
+ addSliderBar(slide, s.label, s.level, 1.8 + i * 0.7);
847
+ });
931
848
 
932
- // Additional quality characteristics
849
+ const qualityY = 1.8 + d.sliders.length * 0.7 + 0.3;
933
850
  slide.addText("品質特性の優先順位", {
934
851
  x: 0.5,
935
- y: 4.8,
852
+ y: qualityY,
936
853
  w: 9.0,
937
854
  h: 0.4,
938
855
  fontSize: 14,
@@ -944,28 +861,18 @@ async function main() {
944
861
  addTable(
945
862
  slide,
946
863
  ["優先度", "品質特性", "理由"],
947
- [
948
- ["1", "正確性", "受注・在庫データの正確性は業務の根幹"],
949
- ["2", "使いやすさ", "小規模チームが日常的に使うため、直感的な操作性が必須"],
950
- ["3", "信頼性", "受注処理の停止は直接的な売上損失につながる"],
951
- ["4", "保守性", "小規模チームでの長期運用を見据えたシンプルな設計"],
952
- ],
953
- { y: 5.2, colW: [0.8, 1.8, 6.4] }
864
+ d.qualityPriorities,
865
+ { y: qualityY + 0.4, colW: [0.8, 1.8, 6.4] }
954
866
  );
955
867
  }
956
868
 
957
- // ───────────────────────────────────────
958
- // Slide 12: 初回のリリースに必要なもの
959
- // ───────────────────────────────────────
869
+ // ─── Slide 12: 初回のリリースに必要なもの ───
960
870
  {
871
+ const d = SLIDE_DATA.initialRelease;
961
872
  const slide = pptx.addSlide();
962
873
  addTitle(slide, "初回のリリースに必要なもの");
963
874
 
964
- addHighlightBox(
965
- slide,
966
- "Phase 2 完了時点で MVP(最小実行可能製品)をリリース",
967
- { y: 1.5, h: 0.7, fontSize: 16 }
968
- );
875
+ addHighlightBox(slide, d.highlight, { y: 1.5, h: 0.7, fontSize: 16 });
969
876
 
970
877
  slide.addText("MVP スコープ", {
971
878
  x: 0.5,
@@ -978,16 +885,7 @@ async function main() {
978
885
  color: COLORS.darkBlue,
979
886
  });
980
887
 
981
- addBullets(
982
- slide,
983
- [
984
- "マルチモール受注管理(楽天市場、Yahoo!、Amazon、au PAY)",
985
- "在庫管理(自社在庫 + Amazon FBA 在庫の統合管理)",
986
- "出荷管理(受注に基づく出荷指示・梱包・配送手配)",
987
- "商品管理(商品マスタの一元管理、各モールへの同期)",
988
- ],
989
- { y: 2.9, h: 2.5, fontSize: 13 }
990
- );
888
+ addBullets(slide, d.mvpScope, { y: 2.9, h: 2.5, fontSize: 13 });
991
889
 
992
890
  slide.addText("リリース戦略", {
993
891
  x: 0.5,
@@ -1000,22 +898,11 @@ async function main() {
1000
898
  color: COLORS.darkBlue,
1001
899
  });
1002
900
 
1003
- addBullets(
1004
- slide,
1005
- [
1006
- "以降のフェーズは段階的にリリースし、フィードバックを反映しながら改善",
1007
- "各フェーズ完了時にステークホルダーレビューを実施し、次フェーズの優先順位を見直す",
1008
- ],
1009
- { y: 5.6, h: 1.5, fontSize: 12 }
1010
- );
901
+ addBullets(slide, d.releaseStrategy, { y: 5.6, h: 1.5, fontSize: 12 });
1011
902
  }
1012
903
 
1013
- // ───────────────────────────────────────
1014
- // Save
1015
- // ───────────────────────────────────────
1016
- const outputPath = resolve(
1017
- "docs/analysis/slide/HCOSS_v0.1.0.pptx"
1018
- );
904
+ // ─── 保存 ───
905
+ const outputPath = resolve(`docs/analysis/slide/${meta.outputFileName}`);
1019
906
  const dataBuffer = await pptx.write({ outputType: "nodebuffer" });
1020
907
  writeFileSync(outputPath, dataBuffer);
1021
908
  console.log("Generated:", outputPath);
@@ -68,16 +68,45 @@ node .claude/scripts/generate-inception-deck.mjs
68
68
 
69
69
  #### 生成スクリプトの更新
70
70
 
71
- inception-deck.md の内容が更新された場合、生成スクリプトのデータ部分を更新してから再実行する。
71
+ inception-deck.md の内容が更新された場合、生成スクリプトの `SLIDE_DATA` オブジェクトを更新してから再実行する。
72
72
 
73
73
  1. @docs/analysis/inception-deck.md を読み込む
74
- 2. @.claude/scripts/generate-inception-deck.mjs のスライドデータを更新
74
+ 2. @.claude/scripts/generate-inception-deck.mjs の `SLIDE_DATA` セクションを更新
75
75
  3. `node .claude/scripts/generate-inception-deck.mjs` で再生成
76
76
 
77
+ #### スクリプト構成
78
+
79
+ 生成スクリプトは以下の 4 セクションで構成されている。
80
+
81
+ | セクション | 内容 | 編集対象 |
82
+ | :--- | :--- | :--- |
83
+ | `SLIDE_DATA` | プロジェクト固有のデータ(テキスト・数値) | 毎回更新 |
84
+ | テーマ設定 | カラー・フォント定義 | 通常変更不要 |
85
+ | ヘルパー関数 | スライド部品の描画ロジック | 通常変更不要 |
86
+ | スライド生成 | `SLIDE_DATA` を読み取り 12 枚を生成 | 通常変更不要 |
87
+
88
+ `SLIDE_DATA` の各キーがスライドに対応している。
89
+
90
+ | キー | 対応スライド |
91
+ | :--- | :--- |
92
+ | `meta` | メタ情報(author, title, version, date, outputFileName) |
93
+ | `titleSlide` | Slide 1: タイトル |
94
+ | `whyAreWeHere` | Slide 2: 我われはなぜここにいるのか |
95
+ | `elevatorPitch` | Slide 3: エレベーターピッチ |
96
+ | `values` | Slide 4: どんな価値をもたらすのか? |
97
+ | `scope` | Slide 5: やらないことリスト |
98
+ | `stakeholders` | Slide 6: プロジェクトコミュニティ |
99
+ | `technicalSolution` | Slide 7: 技術的な解決策の概要 |
100
+ | `risks` | Slide 8: 夜も眠れなくなるような問題 |
101
+ | `team` | Slide 9: 俺たちの "A チーム" |
102
+ | `timeline` | Slide 10: 期間を見極める |
103
+ | `tradeoffs` | Slide 11: トレードオフ・スライダー |
104
+ | `initialRelease` | Slide 12: 初回のリリースに必要なもの |
105
+
77
106
  #### バージョン管理
78
107
 
79
- - 出力ファイル名のバージョン(例: `HCOSS_v0.1.0.pptx`)はリリースバージョンに合わせて更新する
80
- - スクリプト内の `outputPath` と `pptx.title` を同時に更新すること
108
+ - 出力ファイル名は `SLIDE_DATA.meta.outputFileName` で指定する(例: `PROJECT_v0.1.0.pptx`)
109
+ - `meta.title` と `meta.outputFileName` を同時に更新すること
81
110
 
82
111
  ### 6. 注意事項
83
112
 
@@ -91,13 +120,14 @@ inception-deck.md の内容が更新された場合、生成スクリプトの
91
120
 
92
121
  1. `npm install pptxgenjs`(初回のみ)
93
122
  2. @docs/analysis/inception-deck.md の内容を確認
94
- 3. `node .claude/scripts/generate-inception-deck.mjs` を実行
95
- 4. @docs/analysis/slide/HCOSS_v0.1.0.pptx が生成されたことを確認
123
+ 3. @.claude/scripts/generate-inception-deck.mjs`SLIDE_DATA` をプロジェクト固有の内容に書き換える
124
+ 4. `node .claude/scripts/generate-inception-deck.mjs` を実行
125
+ 5. @docs/analysis/slide/ に .pptx が生成されたことを確認
96
126
 
97
127
  ### インセプションデッキ更新後のスライド再生成
98
128
 
99
129
  1. @docs/analysis/inception-deck.md の更新内容を確認
100
- 2. @.claude/scripts/generate-inception-deck.mjs のスライドデータを更新
130
+ 2. @.claude/scripts/generate-inception-deck.mjs の `SLIDE_DATA` を更新
101
131
  3. `node .claude/scripts/generate-inception-deck.mjs` を実行
102
132
 
103
133
  ### 関連スキル
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k2works/claude-code-booster",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
4
4
  "description": "AI Agent Development Support Tool",
5
5
  "main": "main.js",
6
6
  "bin": {