diff --git a/docs/specification/06_development_guide.md b/docs/specification/06_development_guide.md index 87fa6cc..d015e9b 100644 --- a/docs/specification/06_development_guide.md +++ b/docs/specification/06_development_guide.md @@ -41,3 +41,15 @@ - **非同期処理**: SQLite 操作や通信はすべて `tokio` ランタイム上で行い、UI をブロックしないようにします。 - **ログ**: `log::info!` / `log::error!` を使用してください。ログは `src-tauri/logs/` に自動出力されます。 - **テスト**: ロジックの変更後は必ず `scripts/test_mcp_client.mjs` を実行し、既存ツールが壊れていないか確認してください。 + +## 6. Issue管理ルール + +GitBucket との連携においては、以下のルールに従います。 + +- **同期方向**: 原則として GitBucket が正(Source of Truth)です。 +- **自動同期**: `node tools/scripts/sync_issues.mjs` でローカル Markdown とリモート Issue を同期します。 +- **Issueのクローズ**: + - GitBucket API(PATCH)の制約により、スクリプトからの自動クローズは行いません。 + - 作業完了後、ローカル Markdown の `state` を `closed` にして同期スクリプトを実行すると、**手動クローズ用のURL**が表示されます。 + - 表示されたURLからブラウザで手動クローズを行ってください。 +- **Git追跡除外**: `docs/issues/` は `.gitignore` により Git 追跡から除外されています。個々の Issue の更新履歴は GitBucket 側で管理されます。 diff --git "a/journals/20260223-0006-Issue\346\211\213\345\213\225\347\256\241\347\220\206\343\203\253\343\203\274\343\203\253\343\201\256\347\255\226\345\256\232.md" "b/journals/20260223-0006-Issue\346\211\213\345\213\225\347\256\241\347\220\206\343\203\253\343\203\274\343\203\253\343\201\256\347\255\226\345\256\232.md" new file mode 100644 index 0000000..6789d48 --- /dev/null +++ "b/journals/20260223-0006-Issue\346\211\213\345\213\225\347\256\241\347\220\206\343\203\253\343\203\274\343\203\253\343\201\256\347\255\226\345\256\232.md" @@ -0,0 +1,36 @@ +# 作業報告: Issue手動管理ルールの策定と同期ツールの改良 + +## 1. 作業実施の理由と指示 + +- **背景**: GitBucket APIの制限(PATCHメソッドによるIssue状態変更が404エラーになる)により、同期スクリプト完全自動でのIssueクローズが不可能であることが判明した。 +- **意図と指示**: 無理にAPIでの自動化を追及せず、実用性を重視して「クローズのみ手動で行う」という運用ルールを策定し、ツール側でその操作を支援(URL通知)するように改良すること。また、このルールを開発ガイドに追加すること。 + +## 2. 指摘事項とその対応 + +- **指摘**: 同期スクリプトがエラーで停止してしまう。 + - **対応**: `updateRemoteIssue` 関数内で 404 エラーを個別にキャッチし、例外を投げずに「手動操作が必要」という警告と対象IssueのURLをコンソールに表示するよう変更した。 +- **指摘**: ルールを明文化してほしい。 + - **対応**: `docs/specification/06_development_guide.md` に「6. Issue管理ルール」のセクションを新設。クローズ作業が手動であること、および同期ツールの役割を明確に記載した。 + +## 3. 作業詳細 + +AIエージェントは以下の作業を実行した: + +- `tools/scripts/sync_issues.mjs` の通信ロジックを修正。PATCHの失敗を検知してURLをリマインドする機能を実装。 +- `docs/specification/06_development_guide.md` を更新し、Issue追跡除外(.gitignore)と手動クローズ運用をルール化。 +- 改良後のスクリプトを実行し、Issue #2 に対して正しいURLリマインドが表示されることを検証。 + +## 4. AI視点での結果 + +```mermaid +graph TD + A[Local Markdown closed] --> B(sync_issues.mjs) + B --> C{API PATCH issue} + C -- 404 Error --> D[Print Manual Action Reminder] + D --> E[User clicks URL] + E --> F[Manual Close on Web] + F --> G[Next Sync: Pull closed state] + G --> H[Local Metadata Synced] +``` + +APIの技術的限界を「ルールの明文化」と「補助機能」でカバーする、堅実な運用体制を構築できた。これにより、ユーザーは迷うことなく開発サイクルを回すことが可能になった。 diff --git a/tools/scripts/sync_issues.mjs b/tools/scripts/sync_issues.mjs index 53bafc8..31e68e6 100644 --- a/tools/scripts/sync_issues.mjs +++ b/tools/scripts/sync_issues.mjs @@ -89,7 +89,18 @@ async function updateRemoteIssue(number, title, body, state) { console.log(`Pushing changes to remote issue #${number}...`); - return await apiCall(`${API_BASE}/${number}`, 'PATCH', { title, body, state }); + try { + return await apiCall(`${API_BASE}/${number}`, 'PATCH', { title, body, state }); + } catch (err) { + if (err.message.includes('404')) { + const htmlUrl = `https://gitbucket.tmworks.club/dtmoyaji/TelosDB/issues/${number}`; + console.warn(`\n[Manual Action Required]`); + console.warn(`GitBucket API (PATCH) returned 404. Your version might not support issue updates via API.`); + console.warn(`Please manually close issue #${number} at: ${htmlUrl}\n`); + return { _manual: true, html_url: htmlUrl }; + } + throw err; + } } async function createRemoteIssue(title, body) { @@ -154,10 +165,14 @@ } const updated = await updateRemoteIssue(idStr, meta.title, body, meta.state || 'open'); - // Update local metadata timestamp to match remote - const newMeta = { ...meta, state: updated.state, updated_at: updated.updated_at }; - fs.writeFileSync(filePath, stringifyMarkdown(newMeta, updated.body)); - console.log(`[Pushed] Updated #${idStr} on remote.`); + if (updated && !updated._manual) { + // Update local metadata timestamp to match remote + const newMeta = { ...meta, state: updated.state, updated_at: updated.updated_at }; + fs.writeFileSync(filePath, stringifyMarkdown(newMeta, updated.body)); + console.log(`[Pushed] Updated #${idStr} on remote.`); + } else { + console.log(`[Skip] Remote update for #${idStr} requires manual intervention or failed.`); + } // Remove from remote map so we don't overwrite it in Step 2 remoteMap.delete(idStr); }