GitHub Spec KitでGitHub Projects用のブラウザ拡張作ってみた
こんにちは!株式会社コミュニティオのしまだい(@cimadai)です。
今回は、GitHub Spec Kitを使って「GitHub Projectsで便利なブラウザ拡張」を作った話を紹介します。
背景 / 動機
弊社ではGitHub Projectsのカンバンを使ってIssueを管理し、そのIssueをAgentに依頼しつつ開発をしているのですが、カンバン上のIssueのIterationや独自のCategory(カスタムフィールド)を更新するのにわざわざ毎回Issueの詳細画面を開く必要があり大変面倒に感じていました。
「カードを右クリックして即変更」できればな~と思って、最近話題のSpec Kitを使いつつGithub Copilotと一緒にブラウザ拡張を作ることにしました。
Spec Kit とは?
Spec Kit とは ユーザーの要望を元にソフトウェアの仕様を定義し、実装計画からタスク分解をしてくれるツールキットです。
/specify
コマンドで仕様を作成し、 /plan
コマンドで実装計画を作り、 /task
コマンドでタスク分解を行います。
要件
それではやっていきましょう。今回の私の要件を以下のように定義してみました。
Github Project の Kanban 上で issue の Iteration / Category(Custom field) を詳細画面へ遷移せず右クリック操作で素早く変更したい
この要件を元に、Spec Kitで仕様を作っていきたいと思います。
Spec Kitをセットアップする
まずはSpec Kitを使うために、以下のReadmeを参考にセットアップを進めます。
すでにブラウザエクステンションを作る用のリポジトリがありましたので、そこにSpec Kitを導入しました。
uvx --from git+https://github.com/github/spec-kit.git specify init --here
initを実行すると、どのAIアシスタントを使うか聞かれますので、好きなものを選びます。
弊社ではGithub Copilotをメインで使っていますので、copilot
を選びました。
すると、.github/prompts
ディレクトリが生成されます。
中には specify.prompt.md
plan.prompt.md
task.prompt.md
の3つのプロンプトが入っています。
これらはCopilotのチャット欄からそれぞれ /specify
/plan
/task
コマンドとして呼び出すことができます。
そのまま実行すると、以降の仕様や計画がすべて英語で生成されてしまいますので、以下の記事を参考にさせていただき、日本語で使えるようにしました。
/specify
)
仕様を作る (おもむろにCopilotのチャットを開き、以下のように依頼をします。
/specify Github Projectのkanbanで、issueのIterationやCategoryの変更がkanbanからできず、各Issueの詳細画面に遷移してからじゃないと設定できないのが面倒です。
Browser Extensionで解決したいです。
このプロジェクトは複数のブラウザエクステンションがまとまっています。
ディレクトリごとに別のエクステンションになるので、今回作成するエクステンションもディレクトリを作成してその中に作ってください
すると、以下の仕様が生成されました。
生成された仕様
# Feature Specification: GitHub Project Kanban インライン編集 (Category / Iteration)
**Feature Branch**: `001-github-kanban-inline`
**Created**: 2025-09-09
**Status**: Draft
**Input**: User description: "Github Project の Kanban 上で issue の iteration / category(Custom field) を詳細画面へ遷移せず右クリック操作で素早く変更したい"
---
## User Scenarios & Testing *(mandatory)*
### Primary User Story
プロジェクトボード (GitHub Project の Kanban) 上で課題を整理している利用者は、カードを開かずに右クリックだけで Categoryや Iteration を即座に変更し、作業分類やスプリントを高速に整えたい。これにより文脈切り替えやページ遷移の待ち時間を削減し、ボード編集効率を高める。
### Acceptance Scenarios
1. Given ボード上に Issue カードが並んでいる When 任意のカードを右クリック Then 拡張機能の独自コンテキストメニューが表示され Category / Iteration の編集入口が見える
2. Given 既に Category=「動作」が設定された Issue カード When 右クリックメニューから Category -> 「コード」を選択 Then カードの Category 表示が 1 秒以内に「コード」に更新されページ全体リロードは発生しない
3. Given Iteration 未設定の Issue カード When メニューから任意の利用可能 Iteration を選択 Then カード上 (またはその近傍) に Iteration が反映される
4. Given ネットワーク一時不通 When Category 変更を試行 Then 失敗を日本語メッセージで通知し再試行手段が提示され元の値は変わらない
5. Given 同一ボード上で複数カードを連続して編集 When 直前の編集が完了している状態で次のカードを右クリック Then 新しいターゲットのみが正しく更新され前の結果が誤って再適用されない
6. Given 権限が無いユーザー (プロジェクト編集権限不足) When 変更操作を実行 Then 権限不足メッセージが表示され変更は行われない
7. Given ボード外 (空白領域) を右クリック When 操作 Then 拡張機能メニューは表示されない (既存ブラウザ / GitHub 既定のメニューのみに留まる)
### Edge Cases
- Category 未設定 (null) のカード: メニュー表示時に「未設定」を視覚区別 (チェック無し) として扱い変更後に初回設定が反映される。
- Iteration が期限切れ / アーカイブ済み: 選択肢リストには含めない (表示方針を Assumptions で定義)。
- 利用可能 Iteration 数が多い (>20): メニュー表示遅延は 1 秒未満でなければならない。
- 多重連打: 同一フィールドに対し並列更新要求が起きた場合は最後に確定した選択が結果となる (中間状態は破棄)。
- オフライン状態検出: 操作時に即座に失敗通知し保留キューには積まない。
---
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: ボード上 Issue カードを右クリックした際、対象カードに紐づく独自コンテキストメニュー (日本語ラベル) を表示できること。
- **FR-002**: メニューは Category 選択を提供し、現在値を視覚的に示す (例: チェック状態)。
- **FR-003**: メニューは利用可能な Iteration 一覧を表示し、現在選択中 Iteration を視覚的に示す。
- **FR-004**: Category を選択した場合、当該 Issue の Project Custom Field「category」値が 1 秒以内に更新され UI に反映されること (ページ全体リロードなし)。
- **FR-005**: Iteration を選択した場合、当該 Issue の Project Iteration フィールドが 1 秒以内に更新され UI に反映されること (ページ全体リロードなし)。
- **FR-006**: 更新処理は失敗時にユーザーへ日本語メッセージ (簡潔: 失敗理由 + 再試行指示) を表示し、UI 表示値は失敗前の状態へ保全する。
- **FR-007**: コンテキストメニューはボード外領域や Issue 以外の要素を右クリックした場合に表示されない。
- **FR-008**: 連続して別カードを右クリックした場合、前カードのメニューを自動で閉じ最新カードのみが対象となる。
- **FR-009**: 複数ブラウザタブ / ウィンドウで同時利用時、それぞれが正しいカード識別を行い競合せずに動作する。
- **FR-010**: ユーザー権限不足 (書き込み不可) の場合、編集系選択肢は非活性表示または選択時に即時警告する。
- **FR-011**: 操作完了後 2 秒以内にユーザーは視覚的フィードバック (値更新 / 簡易トースト等) により成功を認識できる。
- **FR-012**: Iteration / Category の現在値キャッシュが存在する場合でも明示的選択で最新値取得と整合性検証を最小 1 回実施する。
- **FR-013**: 拡張機能は最小限のファイル構���で (Manifest + コンテンツスクリプト + 必要最小追加ファイル) 動作する (簡素性基準: 追加ファイル 6 未満)。
- **FR-014**: メニュー表示および値更新処理はキーボード操作 (メニュー開閉は標準右クリック前提、選択肢内フォ���カス移動 / Enter 決定) によるアクセシビリティを阻害しない。
- **FR-015**: 同一フィールドへの短時間 (500ms 未満間隔) の再選択が行われた場合、古い保留中更新は破棄または統合され最終選択のみ適用される。
### Non-Functional Requirements
- **NFR-001**: メニュー初回表示 (右クリックから表示完了) までの体感遅延は 300ms 以内。ネットワーク待機が必要な場合はプレースホルダを即時表示し遅延体感を抑制。
- **NFR-002**: 主要操作 (Category / Iteration 更新) の成功率は正常ネットワーク条件下で 99% 以上。
- **NFR-003**: エラー表示メッセージは 120 文字以内の日本語で、再試行手段を含む。
- **NFR-004**: ボード DOM 構造変更 (軽微なクラス名追加等) に対して選択ロジックが壊れにくい (セマンティック属性 / 安定識別子を優先)。
- **NFR-005**: 追加によるページ総リソース読み込み増加 (未キャッシュ時) は 200KB (圧縮後) 未満。
### Key Entities
- **Issue カード**: Kanban 上に表示される単一課題。識別子 (Issue ID / URL 由来 ID)、現在の Category、Iteration 情報を保持。
- **Category 値**: Custom fieldで設定された値のいずれか。未設定を許容。
- **Iteration 値**: プロジェクトで定義された期間単位。状態 (アクティブ / 未来 / 過去) を持つが過去状態は選択対象外 (Assumptions 参照)。
- **コンテキストメニュー**: 右クリック発火で表示。二層構造 (Category, Iteration) の選択肢グループ。
- **ユーザー**: プロジェクト閲覧権限を持つ。編集権限有無により操作可否が異なる。
### Assumptions & Dependencies
- GitHub Project は新しいボード形式 (Iteration / Custom fields 利用可) を前提。
- Iteration の「過去終了済み」または「アーカイブ」状態は選択候補から除外。
- Category フィールド名は一意で値の変更頻度は低い。
- ユーザーは対象 Issue 編集権限 (書き込み) を通常保有している。
- ネットワーク遅延は通常 < 800ms、これを超える場合進捗状態 (ローディング表示) が必要。
- ブラウザは Chromium 系最新版を想定。
### Success Metrics
- 平均単一編集操作完了時間 (右クリック→反映) < 2 秒。
- 連続 10 件編集時の総所要時間 (従来: 詳細遷移あり) 比 50%以上短縮。
- エラー率 < 1% (正常ネットワーク)。
- 初回利用 (未読ユーザー) の操作成功率 95% 以上 (UI 自明性)。
---
## Review & Acceptance Checklist
### Content Quality
- [x] No implementation detail (特定 API エンドポイント / コード構造 未記載)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed
### Requirement Completeness
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified
---
## Execution Status
- [x] User description parsed
- [x] Key concepts extracted
- [x] Ambiguities resolved via assumptions
- [x] User scenarios defined
- [x] Requirements generated
- [x] Entities identified
- [x] Review checklist passed
---
/plan
)
これを元に計画を立てる(次に /plan
コマンドを使って実装計画を立てます。
実際に生成された計画は以下のようになりました。
生成された実装計画
# Implementation Plan: GitHub Project Kanban インライン編集 (Category / Iteration)
**Branch**: `001-github-kanban-inline` | **Date**: 2025-09-09 | **Spec**: ./spec.md
**Input**: Feature specification from `/specs/001-github-kanban-inline/spec.md`
## Execution Flow (/plan command scope)
(本計画はテンプレート手順 1-7 を踏襲。Phase2 以降は未実行)
## Summary
GitHub Project (Projects v2) の Kanban ボード上で Issue カードを右クリックし、ページ遷移なしで Custom Field: Category と Iteration を即時変更するシンプルな Chrome Extension を提供する。UI はコンテンツスクリプトで動的挿入する最小構成 (manifest.json + content script + style + 1 ユーティリティ) とし、GitHub ページ既存の認証コンテキストを再利用した GraphQL Mutation (updateProjectV2ItemFieldValue) を直接呼び出して反映。表示値は DOM 差分更新で即時フィードバック。失敗時は小型トースト(日本語)で再試行案内。外部ビルド/フレームワーク不要。
## Technical Context
**Language/Version**: JavaScript (ES2020 相当) / CSS / HTML (拡張マニフェスト v3)
**Primary Dependencies**: なし (純粋ブラウザ API + GitHub GraphQL endpoint)
**Storage**: chrome.storage.local (必要時のみ: フィールド ID キャッシュ)
**Testing**: 手動テスト + 最小 DOM 抽出関数の単体テスト (後続で検討)
**Target Platform**: Chromium (Chrome, Edge) GitHub Web UI 上
**Project Type**: single (拡張 1 プロジェクト)
**Performance Goals**: メニュー表示 300ms 以内 / 更新反映 1s 以内
**Constraints**: 追加圧縮後 <200KB / ネットワーク遅延 <800ms 想定 / 権限最小
**Scale/Scope**: 単一ユーザー操作・同時編集軽量 (< 数十操作/分)
## Constitution Check
**Simplicity**:
- Projects: 1 (kanban-inline-edit のみ) → OK
- 追加ラッパ/過剰パターン: 不要 → 直接 DOM + fetch
- 単一データモデル: ProjectItem + FieldValue で十分
**Architecture**:
- ライブラリ分割不要 (規模小) → OK
- CLI なし (拡張特性) → 許容 (複雑化回避)
- llms.txt 等生成不要 (小規模)
**Testing (NON-NEGOTIABLE)**:
- 後続タスクで DOM 解析/Mutation ペイロード生成関数を先にテスト化 (RED→GREEN) 計画
- 外部モック最小。GraphQL 呼び出しは fetch ラッパを抽象化しテストでペイロード検証。
**Observability**:
- console.debug に統一プレフィックス [KINLINE] を付与
- 失敗時トースト + console.error で詳細
**Versioning**:
- 初期版 0.1.0 (BUILD はコミットでインクリメント想定)
→ 初期 Constitution Check: PASS (逸脱なし)
## Project Structure
拡張コードは `kanban-inline-edit/` 直下 (既存他拡張と対称)。src ディレクトリ分離は不要。最小ファイル: manifest.json, content.ts, style.css, menu.html(またはテンプレート文字列), util.js (GraphQL/DOM ヘルパ)。
**Structure Decision**: Option 1 (single) を簡略化した extension ディレクトリ。
## Phase 0: Outline & Research (結果要約)
### Unknowns & Resolution
| 項目 | Unknown | Decision | Rationale | Alternatives |
|------|---------|----------|-----------|--------------|
| GraphQL エンドポイント | Web UI から安全に呼べるか | `https://api.github.com/graphql` + Authorization ヘッダー (既存ページから token 抽出挑戦→失敗時ユーザ入力) | 公式サポート / 安定性 | 内部相対 /graphql (内部仕様依存で不安定) |
| 認証トークン取得 | 自動抽出か設定 UI 必要か | meta[name='csrf-token'] 経路は GraphQL 認証不可 → fallback 簡易プロンプト (localStorage 保存) | ファイル追加最小化 (オプションページ不要) | options page 導入 (ファイ���増) |
| フィールド ID/Iteration ID | 取得方法 | 初回 GraphQL query projectV2(fields:first:20) をキャッシュ | 繰返し mutation コスト削減 | ハードコード (移植性低) |
| Category 表示反映 | DOM 再レンダー待機か直接挿入か | カード要素へバッジ挿入/差替 | 即時フィードバック | 全カード再スキャン (過剰) |
| Iteration 表示 | 既存表示部位の有無 | 既存フィールド領域更新; 無ければ末尾に小タグ追加 | 一貫性 | トーストのみ (視認性低) |
| 多重更新制御 | レース発生時処理 | カード単位で pending Map 管理・再選択で前回 Abort | 最終選択優先 | キュー化 (遅延) |
→ research.md に詳細記載 (生成済予定)。
## Phase 1: Design & Contracts (要約)
### Data Model 抽象
- ProjectItem { issueId, projectItemId, category(optionId), iteration(iterationId) }
- FieldCache { categoryFieldId, iterationFieldId, iterationOptions[] }
- PendingUpdate { itemId, fieldId, abortController }
### GraphQL Contracts (概略)
1. Query: プロジェクトアイテムの Field IDs / Iteration values 取得
2. Mutation: updateProjectV2ItemFieldValue (singleSelectOptionId / iterationId)
### Internal Function Contracts
- locateCardElement(evtTarget) -> HTMLElement | null
- extractIds(cardEl) -> { issueId, projectItemId }
- ensureFieldCache(projectId) -> FieldCache
- updateCategory(projectItemId, optionId)
- updateIteration(projectItemId, iterationId)
- renderContextMenu(position, state)
### Quickstart 概要
1. リポジトリ clone → 拡張をデベロッパーモードで読み込み
2. GitHub Project ボードを開く
3. 初回右クリックでトークン未設定なら入力ダイアログ
4. 右クリックメニューから Category/Iteration 変更 → 即時反映
### Post-Design Constitution Check
- 新規複雑度導入なし → PASS
## Phase 2: Task Planning Approach (説明のみ /tasks で生成)
- 入口: Data model & contracts からテストタスク (DOM util / payload build) を RED で作成
- 並列 [P]: DOM 抽出 util, GraphQL payload builder, メニュー DOM/CSS, トースト表示
- シリアル: FieldCache 取得 → 右クリックハンドリング → 更新制御 → 失敗処理
- 受入テストシナリオ: Spec Acceptance Scenarios を統合テスト表現 (後続 manual+script)
## Complexity Tracking
(なし)
## Progress Tracking
**Phase Status**:
- [x] Phase 0: Research complete (/plan command)
- [x] Phase 1: Design complete (/plan command)
- [x] Phase 2: Task planning complete (/plan command - describe approach only)
- [ ] Phase 3: Tasks generated (/tasks command)
- [ ] Phase 4: Implementation complete
- [ ] Phase 5: Validation passed
**Gate Status**:
- [x] Initial Constitution Check: PASS
- [x] Post-Design Constitution Check: PASS
- [x] All NEEDS CLARIFICATION resolved (トークン取得手段: 二段階方針確立)
- [ ] Complexity deviations documented (該当なし)
---
*Based on Constitution (プレースホルダ版)*
/tasks
)
最後に、タスクに分解する(最後に /tasks
コマンドを使ってタスクに分解します。
最後のプロンプトとして、以下を実行すると、tasks.mdが生成されます。
/tasks
生成されたタスク
# Tasks: GitHub Project Kanban インライン編集 (Category / Iteration)
**Input**: /specs/001-github-kanban-inline/ (spec.md, plan.md, research.md, data-model.md, contracts/)
**目的**: 右クリックメニューから Category / Iteration を GitHub Projects v2 上でインライン編集できる最小拡張を TDD で完成させる。
## 実行方針
- TDD: テスト (RED) → 実装 (GREEN) → リファクタ (REFACTOR)
- ファイル数最小: manifest.json, content.ts, style.css + (graphql.js, util.js) + テスト用ファイル群
- GraphQL: project-fields (既存) + update-field (新規) 2 契約
- 競合制御: AbortController
- キャッシュ: FieldCache 10 分 TTL
## 命名/並列ルール
- [P] = 依存/同一ファイル競合なし並列可
- 同一ファイル変更を伴う実装タスクは [P] 付けない
- テストは実装より先行必須
---
## Phase 3.1: Setup
- [ ] T001 仕様再確認: spec.md / plan.md / research.md / data-model.md を読み要件要約 (作業メモのみ) (依存: 無)
- [ ] T002 kanban-inline-edit/package.json 追加 (devDependencies: jest, @jest/environment jsdom) scripts:test 設定 (依存: T001)
- [ ] T003 [P] update-field.graphql 契約ファイル作成 (Mutation updateProjectV2ItemFieldValue) (依存: T001)
- [ ] T004 README (kanban-inline-edit/README.md) 作成: 機能概要/インストール/開発テスト手順 (依存: T001)
- [ ] T005 jest セットアップ: jest.config.js (testEnvironment jsdom, roots) (依存: T002)
## Phase 3.2: Contracts / Unit / Integration Tests (RED)
### Contract Tests
- [ ] T006 [P] contract test (project-fields.graphql) パース/クエリ変数生成関数 test/contracts/projectFields.test.js (RED) (依存: T005)
- [ ] T007 [P] contract test (update-field.graphql) Mutation payload builder test/contracts/updateField.test.js (RED) (依存: T003 T005)
### Core Unit Tests
- [ ] T008 [P] DOM カード検出 util (findCardElement / extractIds) test/unit/domUtils.test.js (RED) (依存: T005)
- [ ] T009 [P] FieldCache 管理 ensureFieldCache (TTL, 保存/再利用) test/unit/fieldCache.test.js (RED) (依存: T005)
- [ ] T010 [P] Abort 制御 (pending map / 再選択で旧 fetch Abort) test/unit/abortControl.test.js (RED) (依存: T005)
### Integration Tests (Acceptance Scenarios → 簡易 jsdom)
- [ ] T011 [P] シナリオ1: 右クリックでメニュー表示 test/integration/menuDisplay.test.js (RED) (依存: T006 T008)
- [ ] T012 [P] シナリオ2: Category 変更→UI 即時反映 (ダミー fetch モック) test/integration/categoryUpdate.test.js (RED) (依存: T007 T009)
- [ ] T013 [P] シナリオ3: Iteration 変更→UI 反映 test/integration/iterationUpdate.test.js (RED) (依存: T007 T009)
- [ ] T014 [P] シナリオ4: ネットワーク失敗→トースト表示 test/integration/errorToast.test.js (RED) (依存: T007)
- [ ] T015 [P] シナリオ5: 連続編集最後のみ適用 test/integration/concurrency.test.js (RED) (依存: T010)
- [ ] T016 [P] シナリオ6: 権限不足 (403 モック) → メッセージ表示 test/integration/permission.test.js (RED) (依存: T007)
- [ ] T017 [P] シナリオ7: ボード外右クリック→メニュー非表示 test/integration/outsideClick.test.js (RED) (依存: T011)
### Additional Edge Tests
- [ ] T018 [P] Category 未設定→初回設定 UI 表示 test/integration/categoryUnset.test.js (RED) (依存: T012)
- [ ] T019 [P] 過去 Iteration 除外 test/integration/iterationFilter.test.js (RED) (依存: T009)
## Phase 3.3: Core Implementation (GREEN)
- [ ] T020 graphql.js 作成: query/mutation builder + fetch (Authorization header 付与 / Abort 対応) (依存: T006 T007)
- [ ] T021 util.js 作成: findCardElement, extractIds, toast, abort 管理 (依存: T008 T010)
- [ ] T022 content.ts リファクタ (dummyUpdate 削除, util/graphql 組込み) (依存: T020 T021)
- [ ] T023 FieldCache 実装 (GraphQL project-fields 呼び出し + TTL) (依存: T009 T020)
- [ ] T024 現在値取得 & メニュー反映 (選択中 Category/Iteration にチェック) (依存: T022 T023)
- [ ] T025 Category 更新 (Mutation 呼び出し / UI 即反映 / rollback) (依存: T022 T024)
- [ ] T026 Iteration 更新 (Mutation 呼び出し / UI 即反映 / rollback) (依存: T022 T024)
- [ ] T027 競合制御 (再選択で旧更新 Abort) (依存: T021 T025 T026)
- [ ] T028 エラーハンドリング (種類別: ネットワーク/403/GraphQL errors) (依存: T025 T026)
- [ ] T029 アクセシビリティ (Esc / 矢印キー / Enter) (依存: T024)
- [ ] T030 キャッシュ期限処理 & 手動再取得 (TTL 超過) (依存: T023)
- [ ] T031 トークン再設定 API window.KINLINE.resetToken 追加 (依存: T020)
## Phase 3.4: Integration / Hardening
- [ ] T032 全統合テスト実行→RED→GREEN 確認 (依存: T020-T031)
- [ ] T033 サイズ計測 (content+util+graphql+style 圧縮概算 <200KB) (依存: T022-T031)
- [ ] T034 パフォーマンス計測 (メニュー生成 DOM 操作計測 console.time) (依存: T024)
- [ ] T035 ログ整備 (console.debug プレフィックス一貫性 [KINLINE]) (依存: T022)
## Phase 3.5: Polish / Docs
- [ ] T036 README 更新: 実装差分/制限/トラブルシュート追記 (依存: T032)
- [ ] T037 バージョン bump 0.1.1 (manifest.json) (依存: T032)
- [ ] T038 不要コメント/デバッグ削減 & 最終 lint (依存: T032)
- [ ] T039 最終確認: Acceptance シナリオ手動チェックリスト (依存: T036-T038)
## 依存関係概要
- Setup (T001-T005) → 全テスト
- Contract/Unit (T006-T010) → 実装 (T020+)
- Integration RED (T011-T019) → 実装後 GREEN 確認 (T032)
- graphql/util (T020-T021) → content リファクタ (T022)
- FieldCache (T023) → メニュー現在値 (T024) → 更新 (T025,T026) → 競合制御 (T027)
- エラー処理 (T028) は更新機能後
- アクセシビリティ (T029) / キャッシュ TTL (T030) / 再設定 (T031) は機能後期
- Hardening/Polish 最終 (T032+)
## 並列実行例
# Phase 3.2 初期 (RED) 並列候補:
T006 T007 T008 T009 T010 T011 T012 T013 T014 T015 T016 T017 T018 T019
# Core 実装並列 (異ファイル):
T020(graphql.js) + T021(util.js) + T023(FieldCache) 同期後 T022
## 並列性検証チェック
- [P] 付きタスクは distinct ファイル (test/ 下個別 or 新規ファイル) に限定
- content.ts を変更する実装タスクは逐次 (T022→T024→T025/26→T027…)
## Validation Checklist (生成時)
- [ ] 全契約(project-fields, update-field) にテスト (T006,T007)
- [ ] 全エンティティ(ProjectItem, FieldCache, CategoryOption, IterationOption, PendingUpdate) → FieldCache/Abort/DOM util テスト対応 (T008,T009,T010)
- [ ] Acceptance シナリオ → T011-T017 + Edge (T018,T019)
- [ ] テストが実装より先行
- [ ] [P] タスクは同一ファイル非競合
---
**実行ガイド**
1. Setup 完了後: `npm test` (最初は全 RED)
2. 実装タスク毎に関連テスト GREEN 化
3. 競合/Abort ログをコンソール検証
4. Hardening 後 manual シナリオ確認 → リリース準備
いざ実装
これを元に、Copilotによろしくで完成!とはいかず、会話と介入(手作業での修正)を繰り返し、3時間程度で完成しました。
GithubのGraphQLのあたりがAIにはうまくできなくて手作業でGraphQLのクエリや好みに合わせた細かい実装をしてしまいましたが、概ねバイブスを感じながらの実装となりました。
高速化やUXなどの改善の余地はありますが、私の課題だった詳細画面を開かないと編集できない、というペインは解決できたので満足の出来でした。
感想
昔の自分のやり方だとこういう自分がちょっと楽するためのツールは「作りながら仕様を固めていく」スタイルを取っていたのですが、Spec Kitを使うことで「最初に仕様を固めてから実装に入る」スタイルに強制されることで事前にどういうことをやりたいかを明確にすることができました。
Copilotと協調した実装のすすめ方としては、こまめにコミットして差分を確認しながら問題があったらRevertしてやり直すというのがやりやすかったです。
仕様では最初はJavaScript & jestになっていますが、最終的にはTypeScript & vitestにしたり、Viteでバンドルするようにしたりと途中で好みの変更も加えていきましたが、そのあたりもCopilotのAgentモードを使いつつ気軽に仕様変更を繰り返すことで柔軟に対応できました。
自分なりの実装のすすめ方やプロジェクトの型を事前に言語化しておき、その知識を盛り込んでいくことでよりやりやすくなるんだろうと思います。
今回はあまりブラウザ拡張に慣れていない状態でしたが、実際に仕事で実用に耐える品質のツールがそこそこの時間でできたのは良い驚きがあり、今後もガシガシ使っていきたいですね!
Discussion