@sk8metal/michi-cli 0.2.1 → 0.4.0

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.
Files changed (172) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dist/scripts/config-global.d.ts +10 -0
  3. package/dist/scripts/config-global.d.ts.map +1 -0
  4. package/dist/scripts/config-global.js +111 -0
  5. package/dist/scripts/config-global.js.map +1 -0
  6. package/dist/scripts/confluence-sync.d.ts +22 -4
  7. package/dist/scripts/confluence-sync.d.ts.map +1 -1
  8. package/dist/scripts/confluence-sync.js +22 -12
  9. package/dist/scripts/confluence-sync.js.map +1 -1
  10. package/dist/scripts/jira-sync.d.ts.map +1 -1
  11. package/dist/scripts/jira-sync.js +201 -167
  12. package/dist/scripts/jira-sync.js.map +1 -1
  13. package/dist/scripts/list-projects.js.map +1 -1
  14. package/dist/scripts/multi-project-estimate.js.map +1 -1
  15. package/dist/scripts/phase-runner.d.ts +1 -1
  16. package/dist/scripts/phase-runner.d.ts.map +1 -1
  17. package/dist/scripts/phase-runner.js +295 -522
  18. package/dist/scripts/phase-runner.js.map +1 -1
  19. package/dist/scripts/pre-flight-check.d.ts.map +1 -1
  20. package/dist/scripts/pre-flight-check.js +10 -6
  21. package/dist/scripts/pre-flight-check.js.map +1 -1
  22. package/dist/scripts/resource-dashboard.js.map +1 -1
  23. package/dist/scripts/spec-impl-workflow.js +1 -1
  24. package/dist/scripts/spec-impl-workflow.js.map +1 -1
  25. package/dist/scripts/template/renderer.d.ts +1 -1
  26. package/dist/scripts/template/renderer.d.ts.map +1 -1
  27. package/dist/scripts/test-interactive.d.ts.map +1 -1
  28. package/dist/scripts/test-interactive.js +0 -15
  29. package/dist/scripts/test-interactive.js.map +1 -1
  30. package/dist/scripts/test-new-features.js +6 -3
  31. package/dist/scripts/test-new-features.js.map +1 -1
  32. package/dist/scripts/test-spec-generator.d.ts.map +1 -1
  33. package/dist/scripts/test-spec-generator.js +1 -2
  34. package/dist/scripts/test-spec-generator.js.map +1 -1
  35. package/dist/scripts/utils/config-loader.d.ts +7 -2
  36. package/dist/scripts/utils/config-loader.d.ts.map +1 -1
  37. package/dist/scripts/utils/config-loader.js +79 -8
  38. package/dist/scripts/utils/config-loader.js.map +1 -1
  39. package/dist/scripts/utils/config-sections.d.ts +54 -0
  40. package/dist/scripts/utils/config-sections.d.ts.map +1 -0
  41. package/dist/scripts/utils/config-sections.js +178 -0
  42. package/dist/scripts/utils/config-sections.js.map +1 -0
  43. package/dist/scripts/utils/config-validator.d.ts +4 -0
  44. package/dist/scripts/utils/config-validator.d.ts.map +1 -1
  45. package/dist/scripts/utils/config-validator.js +57 -1
  46. package/dist/scripts/utils/config-validator.js.map +1 -1
  47. package/dist/scripts/utils/confluence-approval.d.ts.map +1 -1
  48. package/dist/scripts/utils/confluence-approval.js +5 -3
  49. package/dist/scripts/utils/confluence-approval.js.map +1 -1
  50. package/dist/scripts/utils/confluence-hierarchy.d.ts.map +1 -1
  51. package/dist/scripts/utils/confluence-hierarchy.js.map +1 -1
  52. package/dist/scripts/utils/interactive-helpers.d.ts +32 -0
  53. package/dist/scripts/utils/interactive-helpers.d.ts.map +1 -0
  54. package/dist/scripts/utils/interactive-helpers.js +92 -0
  55. package/dist/scripts/utils/interactive-helpers.js.map +1 -0
  56. package/dist/scripts/utils/jira-issue-type-fetcher.d.ts.map +1 -1
  57. package/dist/scripts/utils/jira-issue-type-fetcher.js +27 -18
  58. package/dist/scripts/utils/jira-issue-type-fetcher.js.map +1 -1
  59. package/dist/scripts/utils/release-notes-generator.d.ts.map +1 -1
  60. package/dist/scripts/utils/release-notes-generator.js +2 -1
  61. package/dist/scripts/utils/release-notes-generator.js.map +1 -1
  62. package/dist/scripts/utils/spec-updater.d.ts +19 -0
  63. package/dist/scripts/utils/spec-updater.d.ts.map +1 -1
  64. package/dist/scripts/utils/spec-updater.js.map +1 -1
  65. package/dist/scripts/utils/tasks-converter.d.ts.map +1 -1
  66. package/dist/scripts/utils/tasks-converter.js +2 -2
  67. package/dist/scripts/utils/tasks-converter.js.map +1 -1
  68. package/dist/scripts/utils/tasks-format-validator.d.ts.map +1 -1
  69. package/dist/scripts/utils/tasks-format-validator.js +0 -12
  70. package/dist/scripts/utils/tasks-format-validator.js.map +1 -1
  71. package/dist/scripts/utils/test-runner.d.ts.map +1 -1
  72. package/dist/scripts/utils/test-runner.js +3 -2
  73. package/dist/scripts/utils/test-runner.js.map +1 -1
  74. package/dist/scripts/validate-phase.d.ts +1 -1
  75. package/dist/scripts/validate-phase.d.ts.map +1 -1
  76. package/dist/scripts/validate-phase.js +12 -62
  77. package/dist/scripts/validate-phase.js.map +1 -1
  78. package/dist/scripts/workflow-orchestrator.d.ts.map +1 -1
  79. package/dist/scripts/workflow-orchestrator.js +11 -16
  80. package/dist/scripts/workflow-orchestrator.js.map +1 -1
  81. package/dist/src/__tests__/integration/setup/claude.test.js +8 -8
  82. package/dist/src/__tests__/integration/setup/claude.test.js.map +1 -1
  83. package/dist/src/__tests__/integration/setup/init.test.d.ts +5 -0
  84. package/dist/src/__tests__/integration/setup/init.test.d.ts.map +1 -0
  85. package/dist/src/__tests__/integration/setup/init.test.js +352 -0
  86. package/dist/src/__tests__/integration/setup/init.test.js.map +1 -0
  87. package/dist/src/cli.d.ts.map +1 -1
  88. package/dist/src/cli.js +29 -21
  89. package/dist/src/cli.js.map +1 -1
  90. package/dist/src/commands/init.d.ts +28 -0
  91. package/dist/src/commands/init.d.ts.map +1 -0
  92. package/dist/src/commands/init.js +490 -0
  93. package/dist/src/commands/init.js.map +1 -0
  94. package/dist/src/commands/setup-existing.d.ts +1 -1
  95. package/dist/src/commands/setup-existing.d.ts.map +1 -1
  96. package/dist/src/commands/setup-existing.js +49 -3
  97. package/dist/src/commands/setup-existing.js.map +1 -1
  98. package/docs/user-guide/getting-started/new-repository-setup.md +1 -1
  99. package/docs/user-guide/getting-started/setup.md +33 -5
  100. package/docs/user-guide/guides/agent-skills-integration.md +16 -11
  101. package/docs/user-guide/guides/customization.md +64 -11
  102. package/docs/user-guide/guides/workflow.md +35 -21
  103. package/docs/user-guide/hands-on/claude-agent-setup.md +192 -50
  104. package/docs/user-guide/hands-on/claude-setup.md +63 -9
  105. package/docs/user-guide/hands-on/cursor-setup.md +9 -8
  106. package/docs/user-guide/hands-on/verification-checklist.md +4 -3
  107. package/docs/user-guide/hands-on/workflow-walkthrough.md +3 -3
  108. package/docs/user-guide/reference/config.md +30 -5
  109. package/docs/user-guide/reference/quick-reference.md +70 -74
  110. package/docs/user-guide/testing/test-planning-flow.md +4 -0
  111. package/package.json +2 -4
  112. package/scripts/config-global.ts +160 -0
  113. package/scripts/confluence-sync.ts +91 -27
  114. package/scripts/jira-sync.ts +284 -218
  115. package/scripts/list-projects.ts +2 -2
  116. package/scripts/multi-project-estimate.ts +3 -3
  117. package/scripts/phase-runner.ts +391 -594
  118. package/scripts/pre-flight-check.ts +20 -9
  119. package/scripts/pre-publish-check.sh +3 -34
  120. package/scripts/resource-dashboard.ts +4 -4
  121. package/scripts/spec-impl-workflow.ts +1 -1
  122. package/scripts/template/renderer.ts +1 -1
  123. package/scripts/test-interactive.ts +0 -19
  124. package/scripts/test-new-features.ts +10 -7
  125. package/scripts/test-npm-package.sh +3 -34
  126. package/scripts/test-spec-generator.ts +3 -7
  127. package/scripts/utils/config-loader.ts +107 -26
  128. package/scripts/utils/config-sections.ts +316 -0
  129. package/scripts/utils/config-validator.ts +66 -1
  130. package/scripts/utils/confluence-approval.ts +8 -6
  131. package/scripts/utils/confluence-hierarchy.ts +27 -27
  132. package/scripts/utils/interactive-helpers.ts +135 -0
  133. package/scripts/utils/jira-issue-type-fetcher.ts +29 -21
  134. package/scripts/utils/release-notes-generator.ts +3 -2
  135. package/scripts/utils/spec-updater.ts +37 -15
  136. package/scripts/utils/tasks-converter.ts +4 -6
  137. package/scripts/utils/tasks-format-validator.ts +0 -13
  138. package/scripts/utils/test-runner.ts +4 -3
  139. package/scripts/validate-phase.ts +21 -80
  140. package/scripts/workflow-orchestrator.ts +16 -25
  141. package/templates/claude/commands/kiro/kiro-spec-impl.md +4 -0
  142. package/templates/claude/commands/kiro/kiro-spec-tasks.md +3 -1
  143. package/templates/claude/commands/michi/confluence-sync.md +8 -2
  144. package/templates/claude/commands/michi/design-review.md +4 -0
  145. package/templates/claude/commands/michi/e2e-plan.md +4 -0
  146. package/templates/claude/commands/michi/license-check.md +4 -0
  147. package/templates/claude/commands/michi/pr-resolve.md +4 -0
  148. package/templates/claude/commands/michi/project-switch.md +8 -2
  149. package/templates/claude/commands/michi/spec-design.md +78 -0
  150. package/templates/claude/commands/michi/spec-impl.md +716 -0
  151. package/templates/claude/commands/michi/test-planning.md +174 -0
  152. package/templates/claude/commands/michi/validate-design.md +58 -0
  153. package/templates/claude/commands/michi/version-audit.md +4 -0
  154. package/templates/michi/cc-sdd-overrides/README.md +58 -0
  155. package/templates/michi/cc-sdd-overrides/settings/rules/design-review-michi.md +53 -0
  156. package/templates/michi/cc-sdd-overrides/settings/templates/specs/init.json +24 -0
  157. package/templates/michi/cc-sdd-overrides/settings/templates/specs/tasks.md +446 -0
  158. package/dist/scripts/config-interactive.d.ts +0 -10
  159. package/dist/scripts/config-interactive.d.ts.map +0 -1
  160. package/dist/scripts/config-interactive.js +0 -372
  161. package/dist/scripts/config-interactive.js.map +0 -1
  162. package/dist/scripts/setup-existing-project.d.ts +0 -15
  163. package/dist/scripts/setup-existing-project.d.ts.map +0 -1
  164. package/dist/scripts/setup-existing-project.js +0 -455
  165. package/dist/scripts/setup-existing-project.js.map +0 -1
  166. package/dist/scripts/setup-interactive.d.ts +0 -10
  167. package/dist/scripts/setup-interactive.d.ts.map +0 -1
  168. package/dist/scripts/setup-interactive.js +0 -413
  169. package/dist/scripts/setup-interactive.js.map +0 -1
  170. package/scripts/config-interactive.ts +0 -550
  171. package/scripts/setup-existing-project.ts +0 -585
  172. package/scripts/setup-interactive.ts +0 -565
@@ -0,0 +1,316 @@
1
+ /**
2
+ * 設定セクションの対話的取得関数
3
+ */
4
+
5
+ import type * as readline from 'readline';
6
+ import { select, confirm, question, multiSelect } from './interactive-helpers.js';
7
+ import type { ProjectMetadata } from './project-meta.js';
8
+
9
+ /**
10
+ * Confluence階層設定
11
+ */
12
+ export interface ConfluenceHierarchyConfig {
13
+ mode?: 'simple' | 'nested';
14
+ parentPageTitle?: string;
15
+ structure?: unknown;
16
+ }
17
+
18
+ /**
19
+ * Confluence設定結果
20
+ */
21
+ export interface ConfluenceConfigResult {
22
+ pageCreationGranularity: string;
23
+ pageTitleFormat?: string;
24
+ hierarchy?: ConfluenceHierarchyConfig;
25
+ }
26
+
27
+ /**
28
+ * JIRA設定結果
29
+ */
30
+ export interface JiraConfigResult {
31
+ createEpic: boolean;
32
+ storyCreationGranularity: string;
33
+ selectedPhases?: string[];
34
+ storyPoints: string;
35
+ }
36
+
37
+ /**
38
+ * ワークフロー設定結果
39
+ */
40
+ export interface WorkflowConfigResult {
41
+ enabledPhases: string[];
42
+ approvalGates?: {
43
+ requirements?: string[];
44
+ design?: string[];
45
+ release?: string[];
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Confluence設定を対話的に取得
51
+ */
52
+ export async function getConfluenceConfig(
53
+ rl: readline.Interface,
54
+ _projectMeta?: ProjectMetadata,
55
+ ): Promise<ConfluenceConfigResult> {
56
+ console.log('\n📄 Confluence設定');
57
+ console.log('='.repeat(60));
58
+
59
+ const granularityChoices = [
60
+ {
61
+ value: 'single',
62
+ label: 'single(1ドキュメント = 1ページ)',
63
+ description: 'デフォルト・現在の動作',
64
+ },
65
+ {
66
+ value: 'by-section',
67
+ label: 'by-section(セクションごとにページ分割)',
68
+ description: '## セクションごとにページを作成',
69
+ },
70
+ {
71
+ value: 'by-hierarchy',
72
+ label: 'by-hierarchy(階層構造)',
73
+ description: '親ページ + 子ページの階層構造',
74
+ },
75
+ {
76
+ value: 'manual',
77
+ label: 'manual(手動指定)',
78
+ description: '設定ファイルで明示的に指定',
79
+ },
80
+ ];
81
+
82
+ const granularity = await select(
83
+ rl,
84
+ 'ページ作成粒度を選択してください:',
85
+ granularityChoices,
86
+ 'single',
87
+ );
88
+
89
+ const config: ConfluenceConfigResult = {
90
+ pageCreationGranularity: granularity,
91
+ };
92
+
93
+ // タイトル形式のカスタマイズ
94
+ const customTitle = await confirm(
95
+ rl,
96
+ 'ページタイトル形式をカスタマイズしますか?',
97
+ false,
98
+ );
99
+
100
+ if (customTitle) {
101
+ const titleFormat = await question(
102
+ rl,
103
+ 'タイトル形式を入力してください(例: {projectName} - {featureName}): ',
104
+ );
105
+ if (titleFormat) {
106
+ config.pageTitleFormat = titleFormat;
107
+ }
108
+ }
109
+
110
+ // 階層構造設定
111
+ if (granularity === 'by-hierarchy' || granularity === 'manual') {
112
+ config.hierarchy = {};
113
+
114
+ if (granularity === 'by-hierarchy') {
115
+ const modeChoices = [
116
+ {
117
+ value: 'simple',
118
+ label: 'simple(親ページ + ドキュメントタイプ子ページ)',
119
+ description: '2階層構造',
120
+ },
121
+ {
122
+ value: 'nested',
123
+ label:
124
+ 'nested(親ページ → ドキュメントタイプ親 → セクション子ページ)',
125
+ description: '3階層構造',
126
+ },
127
+ ];
128
+
129
+ const mode = await select(
130
+ rl,
131
+ '階層構造のモードを選択してください:',
132
+ modeChoices,
133
+ 'simple',
134
+ );
135
+
136
+ config.hierarchy.mode = mode as 'simple' | 'nested';
137
+ }
138
+
139
+ const parentTitle = await question(
140
+ rl,
141
+ '親ページのタイトル形式を入力してください(例: [{projectName}] {featureName}): ',
142
+ );
143
+
144
+ if (parentTitle) {
145
+ config.hierarchy.parentPageTitle = parentTitle;
146
+ } else {
147
+ config.hierarchy.parentPageTitle = '[{projectName}] {featureName}';
148
+ }
149
+
150
+ if (granularity === 'manual') {
151
+ console.log(
152
+ '\n⚠️ manualモードでは、設定ファイルを手動で編集する必要があります。',
153
+ );
154
+ console.log(
155
+ ' hierarchy.structure に各ドキュメントタイプのページ構造を定義してください。',
156
+ );
157
+ }
158
+ }
159
+
160
+ return config;
161
+ }
162
+
163
+ /**
164
+ * JIRA設定を対話的に取得
165
+ */
166
+ export async function getJiraConfig(rl: readline.Interface): Promise<JiraConfigResult> {
167
+ console.log('\n📋 JIRA設定');
168
+ console.log('='.repeat(60));
169
+
170
+ const createEpic = await confirm(rl, 'Epicを作成しますか?', true);
171
+
172
+ const granularityChoices = [
173
+ {
174
+ value: 'all',
175
+ label: 'all(全Storyを作成)',
176
+ description: 'デフォルト',
177
+ },
178
+ {
179
+ value: 'by-phase',
180
+ label: 'by-phase(フェーズごとに作成)',
181
+ description: 'フェーズごとに個別に作成',
182
+ },
183
+ {
184
+ value: 'selected-phases',
185
+ label: 'selected-phases(指定フェーズのみ)',
186
+ description: '選択したフェーズのみ作成',
187
+ },
188
+ ];
189
+
190
+ const granularity = await select(
191
+ rl,
192
+ 'Story作成粒度を選択してください:',
193
+ granularityChoices,
194
+ 'all',
195
+ );
196
+
197
+ const config: JiraConfigResult = {
198
+ createEpic,
199
+ storyCreationGranularity: granularity,
200
+ storyPoints: 'auto', // デフォルト値(後で上書きされる)
201
+ };
202
+
203
+ if (granularity === 'selected-phases') {
204
+ const phaseChoices = [
205
+ // 新ワークフロー構造
206
+ { value: 'spec-init', label: 'Phase 0.0: プロジェクト初期化' },
207
+ { value: 'requirements', label: 'Phase 0.1: 要件定義(Requirements)' },
208
+ { value: 'design', label: 'Phase 0.2: 設計(Design)' },
209
+ { value: 'test-type-selection', label: 'Phase 0.3: テストタイプ選択' },
210
+ { value: 'test-spec', label: 'Phase 0.4: テスト仕様書作成' },
211
+ { value: 'spec-tasks', label: 'Phase 0.5: タスク分割' },
212
+ { value: 'environment-setup', label: 'Phase 1: 環境構築' },
213
+ { value: 'implementation', label: 'Phase 2: TDD実装(Implementation)' },
214
+ { value: 'phase-a', label: 'Phase A: PR前自動テスト' },
215
+ { value: 'testing', label: 'Phase 3: 追加QA(Testing)' },
216
+ { value: 'phase-b', label: 'Phase B: リリース準備テスト' },
217
+ { value: 'release-prep', label: 'Phase 4: リリース準備(Release Preparation)' },
218
+ { value: 'release', label: 'Phase 5: リリース(Release)' },
219
+ ];
220
+
221
+ const selectedPhases = await multiSelect(
222
+ rl,
223
+ '作成するフェーズを選択してください:',
224
+ phaseChoices,
225
+ ['implementation', 'testing'],
226
+ );
227
+
228
+ config.selectedPhases = selectedPhases;
229
+ }
230
+
231
+ const storyPointsChoices = [
232
+ { value: 'auto', label: 'auto(自動抽出)', description: 'デフォルト' },
233
+ { value: 'manual', label: 'manual(手動設定)' },
234
+ { value: 'disabled', label: 'disabled(設定しない)' },
235
+ ];
236
+
237
+ const storyPoints = await select(
238
+ rl,
239
+ 'Story Points設定を選択してください:',
240
+ storyPointsChoices,
241
+ 'auto',
242
+ );
243
+
244
+ config.storyPoints = storyPoints;
245
+
246
+ return config;
247
+ }
248
+
249
+ /**
250
+ * ワークフロー設定を対話的に取得
251
+ */
252
+ export async function getWorkflowConfig(rl: readline.Interface): Promise<WorkflowConfigResult> {
253
+ console.log('\n⚙️ ワークフロー設定');
254
+ console.log('='.repeat(60));
255
+
256
+ const phaseChoices = [
257
+ { value: 'requirements', label: '要件定義(Requirements)' },
258
+ { value: 'design', label: '設計(Design)' },
259
+ { value: 'tasks', label: 'タスク分割(Tasks)' },
260
+ ];
261
+
262
+ const enabledPhases = await multiSelect(
263
+ rl,
264
+ '有効化するフェーズを選択してください:',
265
+ phaseChoices,
266
+ ['requirements', 'design', 'tasks'],
267
+ );
268
+
269
+ const config: WorkflowConfigResult = {
270
+ enabledPhases,
271
+ };
272
+
273
+ const customApprovalGates = await confirm(
274
+ rl,
275
+ '承認ゲートをカスタマイズしますか?',
276
+ false,
277
+ );
278
+
279
+ if (customApprovalGates) {
280
+ config.approvalGates = {};
281
+
282
+ if (enabledPhases.includes('requirements')) {
283
+ const approvers = await question(
284
+ rl,
285
+ '要件定義フェーズの承認者(カンマ区切り、例: pm,director): ',
286
+ );
287
+ if (approvers) {
288
+ config.approvalGates.requirements = approvers
289
+ .split(',')
290
+ .map((s) => s.trim());
291
+ }
292
+ }
293
+
294
+ if (enabledPhases.includes('design')) {
295
+ const approvers = await question(
296
+ rl,
297
+ '設計フェーズの承認者(カンマ区切り、例: architect,director): ',
298
+ );
299
+ if (approvers) {
300
+ config.approvalGates.design = approvers.split(',').map((s) => s.trim());
301
+ }
302
+ }
303
+
304
+ const releaseApprovers = await question(
305
+ rl,
306
+ 'リリースフェーズの承認者(カンマ区切り、例: sm,director): ',
307
+ );
308
+ if (releaseApprovers) {
309
+ config.approvalGates.release = releaseApprovers
310
+ .split(',')
311
+ .map((s) => s.trim());
312
+ }
313
+ }
314
+
315
+ return config;
316
+ }
@@ -5,7 +5,7 @@
5
5
  import { existsSync, readFileSync } from 'fs';
6
6
  import { AppConfigSchema } from '../config/config-schema.js';
7
7
  import type { ZodIssue } from 'zod';
8
- import { getConfig, getConfigPath } from './config-loader.js';
8
+ import { getConfig, getConfigPath, getGlobalConfigPath } from './config-loader.js';
9
9
  import { loadProjectMeta } from './project-meta.js';
10
10
  import {
11
11
  getProjectIssueTypes,
@@ -528,6 +528,71 @@ export async function validateForJiraSyncAsync(
528
528
  return result;
529
529
  }
530
530
 
531
+ /**
532
+ * グローバル設定ファイルをバリデーション
533
+ */
534
+ export function validateGlobalConfig(): ValidationResult {
535
+ const errors: string[] = [];
536
+ const warnings: string[] = [];
537
+ const info: string[] = [];
538
+
539
+ const globalConfigPath = getGlobalConfigPath();
540
+
541
+ if (!existsSync(globalConfigPath)) {
542
+ info.push('Global config file not found. This is optional.');
543
+ return {
544
+ valid: true,
545
+ errors: [],
546
+ warnings: [],
547
+ info,
548
+ };
549
+ }
550
+
551
+ try {
552
+ const content = readFileSync(globalConfigPath, 'utf-8');
553
+ const parsed = JSON.parse(content);
554
+
555
+ // スキーマでバリデーション
556
+ const result = AppConfigSchema.safeParse(parsed);
557
+
558
+ if (!result.success) {
559
+ result.error.issues.forEach((error: ZodIssue) => {
560
+ const path = error.path.map(String).join('.');
561
+ errors.push(`${path}: ${error.message}`);
562
+ });
563
+
564
+ return {
565
+ valid: false,
566
+ errors,
567
+ warnings: [],
568
+ info: [],
569
+ };
570
+ }
571
+
572
+ return {
573
+ valid: errors.length === 0,
574
+ errors,
575
+ warnings,
576
+ info: [],
577
+ };
578
+ } catch (error) {
579
+ if (error instanceof SyntaxError) {
580
+ errors.push(`Invalid JSON in global config: ${error.message}`);
581
+ } else {
582
+ errors.push(
583
+ `Error reading global config file: ${error instanceof Error ? error.message : 'Unknown error'}`,
584
+ );
585
+ }
586
+
587
+ return {
588
+ valid: false,
589
+ errors,
590
+ warnings: [],
591
+ info: [],
592
+ };
593
+ }
594
+ }
595
+
531
596
  // CLI実行
532
597
  if (import.meta.url === `file://${process.argv[1]}`) {
533
598
  const valid = validateAndReport();
@@ -56,7 +56,7 @@ export async function getApprovalStatus(
56
56
  // 承認ラベルをチェック
57
57
  // Confluenceでは通常、承認はカスタムラベルやメタデータで管理される
58
58
  // ここでは "approved" ラベルの存在で判定
59
- const hasApprovedLabel = labels.some((label: any) =>
59
+ const hasApprovedLabel = labels.some((label: { name: string }) =>
60
60
  label.name === 'approved' || label.name === '承認済み'
61
61
  );
62
62
 
@@ -97,8 +97,9 @@ export async function getApprovalStatus(
97
97
  pageId,
98
98
  pageTitle
99
99
  };
100
- } catch (error: any) {
101
- console.error('Failed to get approval status:', error.message);
100
+ } catch (error: unknown) {
101
+ const message = error instanceof Error ? error.message : String(error);
102
+ console.error('Failed to get approval status:', message);
102
103
  throw error;
103
104
  }
104
105
  }
@@ -134,13 +135,14 @@ export async function pollForApproval(
134
135
 
135
136
  // 次のチェックまで待機
136
137
  await new Promise(resolve => setTimeout(resolve, interval));
137
- } catch (error: any) {
138
+ } catch (error: unknown) {
138
139
  // エラーがタイムアウト以外の場合はリトライ
139
- if (error.message.includes('timeout')) {
140
+ const message = error instanceof Error ? error.message : String(error);
141
+ if (message.includes('timeout')) {
140
142
  throw error;
141
143
  }
142
144
 
143
- console.warn('Error checking approval status, will retry:', error.message);
145
+ console.warn('Error checking approval status, will retry:', message);
144
146
  await new Promise(resolve => setTimeout(resolve, interval));
145
147
  }
146
148
  }
@@ -3,7 +3,7 @@
3
3
  * 各パターン(single, by-section, by-hierarchy, manual)に対応
4
4
  */
5
5
 
6
- import type { ConfluenceClient } from '../confluence-sync.js';
6
+ import type { ConfluenceClient, ConfluencePage } from '../confluence-sync.js';
7
7
  import { convertMarkdownToConfluence, createConfluencePage } from '../markdown-to-confluence.js';
8
8
  import type { ProjectMetadata } from './project-meta.js';
9
9
  import type { ConfluenceConfig } from '../config/config-schema.js';
@@ -262,26 +262,26 @@ export async function createSinglePage(
262
262
 
263
263
  // 既存ページを検索
264
264
  const existingPage = await client.searchPage(spaceKey, pageTitle);
265
-
266
- let page: any;
265
+
266
+ let page: ConfluencePage;
267
267
  if (existingPage) {
268
268
  page = await client.updatePage(
269
269
  existingPage.id,
270
270
  pageTitle,
271
271
  fullContent,
272
- existingPage.version.number
272
+ existingPage.version!.number
273
273
  );
274
274
  console.log(`✅ Page updated: ${pageTitle}`);
275
275
  } else {
276
276
  page = await client.createPage(spaceKey, pageTitle, fullContent, labels);
277
277
  console.log(`✅ Page created: ${pageTitle}`);
278
278
  }
279
-
279
+
280
280
  const baseUrl = process.env.ATLASSIAN_URL || '';
281
281
  return {
282
282
  pages: [{
283
283
  id: page.id,
284
- url: `${baseUrl}/wiki${page._links.webui}`,
284
+ url: `${baseUrl}/wiki${page._links!.webui}`,
285
285
  pageId: page.id,
286
286
  title: pageTitle
287
287
  }]
@@ -334,25 +334,25 @@ export async function createBySectionPages(
334
334
 
335
335
  // 既存ページを検索
336
336
  const existingPage = await client.searchPage(spaceKey, pageTitle);
337
-
338
- let page: any;
337
+
338
+ let page: ConfluencePage;
339
339
  if (existingPage) {
340
340
  page = await client.updatePage(
341
341
  existingPage.id,
342
342
  pageTitle,
343
343
  fullContent,
344
- existingPage.version.number
344
+ existingPage.version!.number
345
345
  );
346
346
  console.log(`✅ Page updated: ${pageTitle}`);
347
347
  } else {
348
348
  page = await client.createPage(spaceKey, pageTitle, fullContent, labels);
349
349
  console.log(`✅ Page created: ${pageTitle}`);
350
350
  }
351
-
351
+
352
352
  const baseUrl = process.env.ATLASSIAN_URL || '';
353
353
  pages.push({
354
354
  id: page.id,
355
- url: `${baseUrl}/wiki${page._links.webui}`,
355
+ url: `${baseUrl}/wiki${page._links!.webui}`,
356
356
  pageId: page.id,
357
357
  title: pageTitle
358
358
  });
@@ -449,15 +449,15 @@ export async function createByHierarchySimplePages(
449
449
  }
450
450
  }
451
451
  }
452
-
453
- let childPage: any;
452
+
453
+ let childPage: ConfluencePage;
454
454
  if (existingChild) {
455
- console.log(`📄 Found existing child page: ${existingChild.id} (version ${existingChild.version.number})`);
455
+ console.log(`📄 Found existing child page: ${existingChild.id} (version ${existingChild.version!.number})`);
456
456
  childPage = await client.updatePage(
457
457
  existingChild.id,
458
458
  childPageTitle,
459
459
  fullContent,
460
- existingChild.version.number
460
+ existingChild.version!.number
461
461
  );
462
462
  console.log(`✅ Child page updated: ${childPageTitle}`);
463
463
  } else {
@@ -471,12 +471,12 @@ export async function createByHierarchySimplePages(
471
471
  );
472
472
  console.log(`✅ Child page created: ${childPageTitle} (under ${parentTitle})`);
473
473
  }
474
-
474
+
475
475
  const baseUrl = process.env.ATLASSIAN_URL || '';
476
476
  return {
477
477
  pages: [{
478
478
  id: childPage.id,
479
- url: `${baseUrl}/wiki${childPage._links.webui}`,
479
+ url: `${baseUrl}/wiki${childPage._links!.webui}`,
480
480
  pageId: childPage.id,
481
481
  title: childPageTitle
482
482
  }],
@@ -588,14 +588,14 @@ export async function createByHierarchyNestedPages(
588
588
  // 既存のセクションページを検索(docTypeParentIdで絞り込んで検索)
589
589
  // これにより、同じタイトルでも別機能のページがヒットすることを防ぐ
590
590
  const existingSectionPage = await client.searchPage(spaceKey, sectionPageTitle, docTypeParentId);
591
-
592
- let sectionPage: any;
591
+
592
+ let sectionPage: ConfluencePage;
593
593
  if (existingSectionPage) {
594
594
  sectionPage = await client.updatePage(
595
595
  existingSectionPage.id,
596
596
  sectionPageTitle,
597
597
  fullContent,
598
- existingSectionPage.version.number
598
+ existingSectionPage.version!.number
599
599
  );
600
600
  console.log(`✅ Section page updated: ${sectionPageTitle}`);
601
601
  } else {
@@ -608,11 +608,11 @@ export async function createByHierarchyNestedPages(
608
608
  );
609
609
  console.log(`✅ Section page created: ${sectionPageTitle} (under ${docTypeParentTitle})`);
610
610
  }
611
-
611
+
612
612
  const baseUrl = process.env.ATLASSIAN_URL || '';
613
613
  pages.push({
614
614
  id: sectionPage.id,
615
- url: `${baseUrl}/wiki${sectionPage._links.webui}`,
615
+ url: `${baseUrl}/wiki${sectionPage._links!.webui}`,
616
616
  pageId: sectionPage.id,
617
617
  title: sectionPageTitle
618
618
  });
@@ -731,14 +731,14 @@ export async function createManualPages(
731
731
 
732
732
  // 既存ページを検索(親ページIDが指定されている場合は絞り込んで検索)
733
733
  const existingPage = await client.searchPage(spaceKey, pageTitle, parentPageId);
734
-
735
- let page: any;
734
+
735
+ let page: ConfluencePage;
736
736
  if (existingPage) {
737
737
  page = await client.updatePage(
738
738
  existingPage.id,
739
739
  pageTitle,
740
740
  fullContent,
741
- existingPage.version.number
741
+ existingPage.version!.number
742
742
  );
743
743
  console.log(`✅ Page updated: ${pageTitle}`);
744
744
  } else {
@@ -756,11 +756,11 @@ export async function createManualPages(
756
756
  console.log(`✅ Page created: ${pageTitle}`);
757
757
  }
758
758
  }
759
-
759
+
760
760
  const baseUrl = process.env.ATLASSIAN_URL || '';
761
761
  pages.push({
762
762
  id: page.id,
763
- url: `${baseUrl}/wiki${page._links.webui}`,
763
+ url: `${baseUrl}/wiki${page._links!.webui}`,
764
764
  pageId: page.id,
765
765
  title: pageTitle
766
766
  });