# Changelog — ASA Bridge for Claude

本拡張の version 別変更履歴。`manifest.json` の version は **release 単位で bump**、
その間の変更は同一 version 配下に蓄積する。詳細は memory `project_extension_version_policy.md` 参照。

## 1.0.5.5 (未リリース)

- 会話の読み取り部分を `conversation_parse.js` へ分離し、拡張と公式エクスポート取り込み画面が同じ処理を通るようにした（`content.js` は委譲のみ）。
- PL-136: Claude が出す図（SVG）が PDF で絵にならなかったのを修正。図を画像に焼き直す処理が、上記のファイル分割で呼び出せない場所に取り残されており、通常の保存でも効かなくなっていた（エラーは表に出ないまま）。焼き直しを変換部品側へ移し、拡張と公式エクスポート取り込み画面の両方から同じ処理を通すようにした。

## 1.0.5.4 (2026-08-14)

- PL-133 横展開: 中身のある発言を取り込めずに捨てた時だけ、件数をログに出すようにした（普段は無出力）。Claude 側が新しい種類の部品や別名の描画ツールを出すと、本文が空になって発言ごと消える作りは変えていない。消えた事に気づける状態にするのが目的。
- ストア掲載の短い説明（`extDescription`、ja/en）を書き換え。1.0.5.3 の「要デスクトップアプリ」先頭型は、検索から来た人が最初に読む 1 行が言い訳になっており、競合と並べた時に何ができる拡張か伝わっていなかった。1 文目で保存できる事、2 文目でキャプチャモードなら閉じた後の一時チャットも保存できる事（他が持たない差）を出し、単体では動かない旨は文末に残す。

## 1.0.5.3 (2026-07-09)

- ストア掲載の短い説明（`extDescription`、ja/en）を「要デスクトップアプリ」先頭型に変更。ストア一般公開に伴い、単体では動作しないことを最初に明示する。
- PL-124: コード（`/code`）画面の保存で、画像を読み込んだ結果が空のバブルになっていた不具合を修正。画像を出力に埋め込むようにした（テスト版）。
- PL-120: 共有ページ（`/share/`）を第一級の保存元として対応。埋め込まれた会話から復元し、図・SVG を含めて保存できるようにした。
- PL-116: 保存待ちの取得中に、一定時間を超えたら処理中スピナーを表示するようにした。
- PL-115: 対話型グラフを全タブ分取得し、各図をフル幅の画像として描画・埋め込み。凡例（色＋ラベル）も画像に焼き込んだ。
- PL-112: ネット上の引用画像を取得し、HTML にオフラインで埋め込むようにした。
- PL-110: 複数の画像を均一な正方タイルの格子で並べて表示するようにした（HTML / PDF 共通）。
- PL-107（追補）: claude.ai/code 画面にもウィジェット（保存ボタン等）を表示するよう対応。これまでこの画面は入力欄の形が通常チャットと異なりウィジェットが出なかったが、入力欄から親要素を辿ってその脇に表示する。あわせて、この画面では構造上キャプチャモードが動かない（会話が画面の裏側にあり保存ボタンでまとめて取得する形のため）ので、キャプチャボタンを薄く無効表示にし、マウスを乗せると「このページには対応していません」と理由を出す。通常チャットの見た目・動作は変更なし。
- PL-107: claude.ai/code（コード `</>` モード / Remote Control 画面）の会話保存に対応（テスト版）。この画面は仮想スクロールで画面外の発言が DOM に存在せず、これまで Claude 発言しか取れなかった。裏の events API（`/v1/code/sessions/{id}/events`、`anthropic-version` ヘッダ + cursor ページ送り）から会話全体を取得するよう変更し、ユーザー発言・全履歴・折りたたまれた AI 応答（思考 / ツール実行 / ツール結果）まで「完全な作業ログ」として保存。ページにウィジェットは表示されないが、ツールバーの拡張アイコンから保存できる。取得失敗時は従来の DOM 経路（可視範囲のみ）へ degrade。
- PL-078 Phase C: Claude が出力する図（SVG / Mermaid 等）を HTML / PDF に画像として埋め込み。React/HTML widget 等の静止画化不可なものは従来の `[AI生成: title]` 印を維持。
- PL-095: ツールバーアイコンのポップアップに「保存」「設定」ボタンを追加（ページにウィジェットが出ない状況でも操作可能）。英語環境の保存矢印グリフを全 locale で統一。
- 対象サービス外のページでツールバーポップアップに案内表示（中央寄せ＋アイコン）。保存ボタンの文言を短縮。

## 1.0.4 (2026-05-30)

- ツールバーアイコン押下で「ご意見・不具合報告」ポップアップを追加 (`action.default_popup` = `popup.html` 新設、 従来は押下無反応)。 ボタン押下で共有 Google フォームを新規タブで開き、 対象版は事前入力 (`?usp=pp_url&entry.634899730=Claude`) で自動セット。 新規 `popup.html` / `popup.js` + `_locales` ja/en に `popupHeading` / `popupDesc` / `popupButton` 追加。 権限追加なし (`chrome.tabs.create` は permission 不要)、 既存 content_scripts / NMH / widget 経路は touched 0。 3 版共通実装で `PRODUCT` 定数のみ各版差替 (ChatGPT/Claude/Gemini)。 フォーム本体は日本語のみ (英語需要は実観測後に追加判断)

## 1.0.3 (2026-05-25)
- PL-058 (widget の `△ scroll_snap` icon を撤去、 代わりに `📌 toggle_topmost` icon 追加): widget HTML から scroll_snap button 削除、 同位置に dialog 最前面切替 button 追加。 click で `widget_toggle_topmost` event 送信 → asa_core `handle_widget_toggle_topmost` で `DIALOG_TOPMOST` setting toggle + `set_widget_state({dialog_topmost: <new>})` で widget 即時同期、 既存 `⦿ toggle_realtime` と同 pattern で `data-active="true"` 背景赤化により state 視認可能 (ON = 最前面固定、 OFF = 通常)。 `WIDGET_I18N` から `scroll_snap` key 削除、 `toggle_topmost` key 追加 (= ja/en)。 `applyWidgetState` 拡張 = `caps.toggle_topmost === false` で button hide + `ws.dialog_topmost` で `data-active` 同期。 scroll_snap backend (= `handle_widget_scroll_snap` + dispatcher elif + `scroll_snap_dialog.py` 等) は残置 (= 5/24 user 判定 「backend 維持」 継承)
- PL-039 Phase 1.1: artifact (= Claude `visualize` integration の chat 内 inline render 系) を placeholder 化。 user 実機 dump (= `claude_probe_262cc4.json`) 解析で artifact 機能の正体 = `tool_use` `name:'visualize:read_me'` (AI 内部 design guide 取得 ~20 KB) + `name:'visualize:show_widget'` (SVG/HTML 本体 in `input.widget_code` + label in `input.title`) + `tool_result` (system 確認 msg) の 3 entry pair 構造と確定。 既存「絵 / 画像本体は log に入れない」 contract (= 添付画像 `[添付ファイル: name]` / DALL·E `[画像]`) との整合のため、 `visualize:show_widget` のみ `[AI生成: <title>]` placeholder で枠保持、 raw widget_code (= SVG markup 等) は捨てる。 他 tool_use (`visualize:read_me` / search 等) と全 tool_result は AI 内部情報で user UI に出ないため skip 維持 = 大量 design guide text の混入も同時防止。 generic 設計 (= name prefix match で将来の Claude integration 追加にも拡張容易、 hard-code 形式列挙の負債回避)、 user 提案 (「形式 N 種に handler N 個書くのは大変」) 整合
- PL-039 Phase 1: Claude API hook 経路を新規導入 (= 3 版 capture path parity for release Step 1)。 `page_hook.js` (新規、 MAIN world + document_start) + `content.js` bridge layer + `manifest.json` (`world: "MAIN"` content script + `web_accessible_resources`) を追加。 page_hook が site の `/api/organizations/{org}/chat_conversations/{cid}` GET を fetch/XHR sniff で passive cache、 save click 時 content.js は cache から `chat_messages` array を `current_leaf_message_uuid` → `parent_message_uuid` で parent chain walk して message 化 (= ChatGPT mapping + walker の Claude 版、 構造差は array vs dict)。 cache miss 時は active replay (= `credentials:'include'` + `cache:'no-store'` で site URL 直叩き、 Cookie session のみで認証通る = Phase 0 probe で req_auth_present:false 確認、 ChatGPT の Bearer 抽出 path 不要)。 `content[]` 内 `type:'text'` 採用 / `type:'thinking'` (AI 内部推論) drop。 PL-012 attachment placeholder (= `[添付ファイル: name]`) を API 経路に再配置 = `msg.attachments` / `files` / `sync_sources` 3 bucket union で user turn に注入 (3 版 contract 整合)。 既存 DOM walker は touched せず fallback として残置 (= API miss / 一時 chat 等で発火)。 capture_snapshot / get_realtime_buffer (buffer 空 fallback) / widget save_open の 3 経路を API → DOM 順序の resolve に統合、 realtime mode 周期 refresh 自体の API 統合は別 Phase に分離 (= 単論点 scope 維持)。 Phase 0 (PL-039 charter §試行 Phase 0) で 51 calls 実機 dump 解析を経て endpoint / response shape / 認証方式 / lazy-load 不在 (= `tree=True` で全 turn 一括) を全件確定済
- widget theme を OS `prefers-color-scheme` から **Claude site theme 追従**に変更 + dark theme 時 button hover/active bg を black overlay 化。Claude site dark theme 時に widget hover bg (灰半透明 `rgba(127,127,127,.18)`) が site native button hover の黒系 chip 風と整合していなかった問題を解消。`bindWidgetTheme` が `getComputedStyle(document.documentElement).colorScheme` を判定 (Claude は html element に `color-scheme: dark|light` 設定で theme 切替、 html/body の class は不変 = Tailwind semantic token + CSS var 経由)、`<html>` の `style` / `class` 属性 MutationObserver で site 内 theme toggle 即時追従。widget CSS に `:host([data-theme="dark"]) .asa-dock button:hover { background: #000; }` + `:host([data-theme="dark"]) .asa-dock button:active { background: #000; }` + `:host([data-theme="dark"]) .asa-dock button[data-tooltip]::after { background: #000; }` を追加 (button hover/active bg + tooltip bg を 3 か所共通の純黒 `#000` に統一、 light default の灰系 `#1f1f1f`/`rgba(127,127,127,.18)` から差替)。light default tooltip (`#1f1f1f` bg + `#fff` text) は light theme で問題なしのため touched せず。ChatGPT は site native UI 配色が theme 不変のため横展開対象外、 Gemini は既に site 追従済 = Claude 単版 fix で完結
- widget tooltip を native `title=` 属性から自前 CSS tooltip (`::after` pseudo-element + `data-tooltip` attr) に置換。OS native tooltip の遅延 (~500ms) / 配色 (Win11 = 白bg黒文字) / 位置 (cursor 右下、ばらつき) の 3 症状を一括解消。Shadow DOM scope 内で `padding: 3px 8px 1px` (日本語 baseline 視覚補正) / `line-height: 1.3` (button line-height 36px 継承遮断) / 黒bg `#1f1f1f` 白文字固定 / button 直上 default + 上端余白 < 40px で下方向 flip (`mouseenter` で `getBoundingClientRect` → `data-tooltip-pos` attr toggle) / 120ms hover delay。`applyWidgetI18n` の `el.title = text` は `el.dataset.tooltip = text` に置換 (`aria-label` は維持)
- PL-029 CP3 (`background.js` ASA pre-warm on tab probe、ChatGPT CP2 横展開): `probeClaudeTab` 関数先頭に `void ensureAsaRunning()` (fire-and-forget) を挿入。tab probe = ASA 必要性 signal の proactive trigger 化、tab probe 完了時点 ≈ ASA spawn 並行完了で 1st widget click 時の体感 lag (~300-500ms) 解消。`ensureAsaRunning` singleton (PL-025 CP4) + `state.token` early return guard で重複 spawn / 副作用 0、onUpdated 連発 / bootstrap 起動時 4 回 trigger でも in-flight share or token guard で抑制完備。reactive 経路 (postEvent 401/403 + PL-028 recovery) は touched せず共存。ChatGPT 1 版先導 (CP2) を 1:1 展開
- PL-029 CP4 (`background.js` NMH old port disconnect 化、ChatGPT 同 commit 1:1 横展開): `ensureAsaRunning` 内 `state.nmhPort = port` 上書き前に旧 port を `disconnect()` 呼出。`chrome.runtime.connectNative` で得た port は明示 disconnect しない限り alive 維持 = NMH helper (bat + python.exe = 2 process) も alive 維持で service tab close + 再 open 反復で **NMH helper process が累積する root** を能動 disconnect で旧 helper の stdin EOF → exit させて回避。PL-025 CP4 「NMH disconnect ≠ ASA exit」と整合 (ASA 本体は別 process で alive 維持)
- PL-029 CP5 (`background.js` tab_closed gate 内 NMH disconnect + token reset、ChatGPT 同 commit 1:1 横展開): `tab_closed` gate (PL-021 CP2、残 service tab 0 で `postEvent('tab_closed', ...)` 発火) の **直後**に `state.nmhPort.disconnect()` + `state.token = null` reset を追加。ASA shutdown 確定時に NMH helper も同時 exit で **Python 残置 0** 化、かつ次 service tab open 時の `ensureAsaRunning` が `state.token === null` 経路で **pre-warm 段階で full spawn 発火** = postEvent recovery (PL-028) 待ちの 1st click lag 解消。「(2) 残置 + 再 open で slow spawn」症状を根治
- PL-028 CP3 (`background.js` ASA crash 時 token stale 復旧、ChatGPT CP2 横展開): `postEvent` に `_retried` guard 付き 1 回 retry 経路追加。`fetchError === true` / `status === 0` (ECONNREFUSED = ASA 本体 HTTP server 消失) または `status === 403` (token mismatch、限定 case) を検出して `state.token = null` clear + `ensureAsaRunning` 再実行 + 元 `postEvent` を 1 回 retry。ChatGPT 1 版先導 (CP2) を 1:1 展開、`tool: 'claude_asa'` 差分のみ。PL-025 CP3 fix-C で削除した `port.onDisconnect` token reset の副作用補完
- PL-025 CP4 (ChatGPT CP3 fix-A/fix-C 横展開): `background.js` `ensureAsaRunning` を singleton in-flight promise (`_ensureAsaRunningPromise`) 化 + `port.onDisconnect` 内 `state.token = null` reset 削除。旧実装は (1) `fetchBridgeInfo` の await 中 `nmhConnecting` lock 未設定で 2 連 sendMessage の並行 invocation race 通過 → ASA 2 個 spawn、(2) NMH stub spawn 完了直後 disconnect で token reset → 次 sendMessage の `if (state.token) return true` skip → connectNmh 再突入 → NMH が既存 ASA detect せず 2 個目 spawn の root を残置。Claude content.js は元の PL-024 形 (sync push、save_open 1 発) 維持 = split events 不採用 (charter §scope 縮退判断、sync 経路は visual ack より speed 優先)。ASA crash 時 token stale 復旧は別 PL 起票候補で扱う
- PL-021 CP2 (CP4 横展開): `background.js` `tab_closed` handler に `chrome.tabs.query({url: 'https://claude.ai/*'})` gate 追加 = sender tab 除く残 service tab 数 0 のときだけ `postEvent('tab_closed', ...)` 発火。chrome multi-window / multi-tab で 1 枚閉じだけで ASA 連鎖閉鎖していた root cause を event 元で抑止。ChatGPT 1 版先導 (`86e6b61`) を Claude に同形展開。manifest `host_permissions` `https://claude.ai/*` 既存 = 追加権限不要
- PL-007: DOM 経路の `<table>` を markdown pipe 構文に変換し保存 HTML での表フラット化を解消 (`84a158d`)。`readMessageText` 内 `clone.querySelectorAll('table')` を `tableToMarkdown` 結果のテキストノードに置換、`<thead>/<tbody>/<tfoot>` 跨ぎ・列数不揃い・header 検出に対応
- PL-011: code-block の fence 抜け + 言語ラベル直結 + `<h1>` 誤判定を解消。`<pre class="code-block__code">` を code container として捕捉、inner `<code class="language-X">` から lang 属性 + body を抽出して `code_blocks` 配列に積み marker `[[ASA_CODE_BLOCK_<idx>]]` で本文中を置換。html serializer は ` ```python ` info string 統合 (PL-016 Step 2 相当も同時実装)、md は marker→平文戻し。Claude 固有: `<div role="group" aria-label="...コード">` 内の lang ラベル div / sticky copy button は marker pass-through で skip
- PL-012: file-only upload (本文空 + 添付のみ) の user turn 完全消失を解消。Claude DOM は file-only turn に `[data-testid="user-message"]` を付与しないため `collectMessageNodes` の入口で漏れていた。`[data-testid="file-thumbnail"]` を起点に祖先チェーンから turn container (`flex-wrap` + `justify-end` を持つ祖先) を特定し `data-asa-attachment-only` marker を立てて messages に追加。`readMessageDeep` 内で marker を検出した場合は `readAttachmentContainerDeep` に分岐し、配下 thumbnail の `button[aria-label]` から file 名抽出 (aria-label `<name>, <ext>, <NN行>` の最初のセグメント) を `[添付ファイル: <name>]` 形式で改行区切り注入。composer (送信前 preview) / 既存 user-message と同 turn wrapper 内に重複する container は除外。Gemini PL-017 と症状同一だが Claude は network 経路なし (DOM only) のため deepText 単独修正で完結
- PL-012 (画像/PDF 拡張): 上記 fix が `.txt` 専用の `[data-testid="file-thumbnail"]` selector に依存しており、画像 (PNG/JPG) / PDF 添付では `data-testid` 不在 + 内部 `<img alt>` に file 名格納の DOM 構造に対応できず file-only / mixed 両 turn で再発していた問題を解消。`collectAttachmentOnlyTurns` の起点 selector を `[data-testid="file-thumbnail"], div.group\/thumbnail` の union に拡張、`readAttachmentContainerDeep` の name 抽出を `button[aria-label]` 第一セグメント → `img[alt]` → `innerText` 1 行目の 3 段 fallback chain に整理。container 検出 (`flex-wrap justify-end` ancestor) と turn wrapper 判定は両系統共通のため流用、artifacts panel / file viewer sidebar 内の `group/thumbnail` (depth 0 = `grid grid-cols-...`) は ancestor 不在で自動除外
- PL-013: URL-only msg (本文が外部 link 1 つのみ) の turn 完全消失を解消。`readMessageDeep` / `readMessageText` 内 `clone.querySelectorAll('a[href^="http"]').forEach(a => a.textContent = '')` が **全外部 link** の text を空にしていた (init `23623df` 4/14 から存在の構造バグ)。citation/footnote 内 link は次行の `[data-footnotes], cite, [class*="citation"], [class*="footnote"]` の `node.textContent = ''` で同時 clear されるため冗長、URL-only msg のみが副作用を受け text 空 → `extractMessages` の `.filter(item => item.text)` で drop。fix: 該当 anchor strip 行を 2 箇所削除、citation 経路は line 254 の container strip で完結。X (Twitter) URL ペースト等の頻出 user msg pattern が今回初トリガー
- PL-014: 添付ファイル連投で AI が同応答 (例: "受信を確認した。サンプルとして扱う。") を返した場合に最終 turn が完全消失する問題を解消。`dedupeMessages` 内 `if (key === previousKey) continue;` が adjacent 同 role+text を collapse していたが、Claude UI が legit に **異なる DOM node に同 text** を render する case (regenerate / 連投応答) で user-meaningful turn を 1 つ消す副作用があった。同一 DOM node の重複検出は `collectMessageNodes` の Set-based node identity dedup で既に実施済のため text-based adjacency dedup は冗長 + 過剰。fix: `dedupeMessages` の text-based collapse を撤去 (role normalize / code_blocks default の他作用は維持)。bug は init `23623df` (2026-04-14) から存在、添付連投 + 同応答 pattern 不在で約 3 週間潜伏。DOM 確認 (`Array.from(document.querySelectorAll('[data-is-streaming]')).map(e=>e.innerText.trim().length)` で `[211, 61, 61, 79, 53, 53]` 観測 = 末尾 53,53 の同 text ペア 1 つが drop) で確定
- PL-015: scroll_snap mode で「同応答 template (例: "同じ回答を短く繰り返します。") の最終 turn が完全消失」を解消。`asa_core` 配下に **無く** 各版 `runtime/save_helpers.py` の `merge_scroll_snap_batches` が `role + text[:80]` text-based fingerprint で adjacent dedupe しており、PL-014 と同根の異 DOM node 同 text collapse 副作用があった (PL-014 が content.js dedupeMessages 層、PL-015 が batch merge 層、責務独立)。occurrence-based dedupe (`(role, text, occurrence_within_batch)`) に書換、同 batch 内 N 回目の同 text は同 DOM msg として dedupe、N+1 回目は別 msg として両方 keep。3 版 (Claude/ChatGPT/Gemini) `save_helpers.py` 同形展開
- icon fix: `claude_extension/icons/icon{16,32,48,128}.png` を Claude 専用デザインに差替。従前は ChatGPT 拡張用 icon を流用 (md5 完全一致) しており Chrome 拡張機能管理ページ / extension list で ChatGPT アイコン誤表示。`Claude_ASA/ClaudeASA_icon_C15F3C_1024.png` (1024x1024 RGBA) を Pillow LANCZOS で 4 サイズ resize

## 1.0.2 (2026-04-08)

- 初回 Chrome Web Store 申請版
- `manifest.name` を「ASA Bridge for Claude」に確定
- プライバシーポリシー URL: https://jellycotton.github.io/asa-privacy-policy/
