Skip to content

refactor: デザインシステム整備・コード品質改善 - #2

Merged
fumtas1k merged 6 commits into
mainfrom
develop
Apr 12, 2026
Merged

refactor: デザインシステム整備・コード品質改善#2
fumtas1k merged 6 commits into
mainfrom
develop

Conversation

@fumtas1k

Copy link
Copy Markdown
Owner

Summary

  • カラートークンを CSS 変数に移行(ダークモード対応準備)
  • GS1 DataBar コンポーネントのコード品質改善
  • DADS デザインシステムの設定修正
  • ドキュメント更新チェックの自動化

Changes

refactor: GS1 DataBar コンポーネント改善

  • nextId モジュール変数 → crypto.randomUUID() に変更(StrictMode 対応)
  • inputId を安定した cardId(UUID)ベースに変更
  • buildBwipText の二重呼び出しを変数化
  • parseInt に基数 10 を追加

refactor: カラートークンを CSS 変数に移行

  • colors.* の値を hex → var(--color-*) 参照に変更
  • global.css に色値を一元化。ダークモード追加時は .dark {} を追加するだけでよい
  • CopyButton.tsxJanCode.tsx の hex 直書きも colors.* に統一
  • styles.tsmicrocaption のエイリアスに変更(同一値の重複解消)

fix: DADS warning カラーを WCAG AA 準拠の値に修正

  • --color-warning: #D97706(amber-600、白背景で 3.3:1 → AA 不合格)
  • #854D0E(amber-800)に修正。global.cssSKILL.md 両方を更新

chore: pre-commit フックによるドキュメント更新チェック

  • .githooks/pre-commit を追加
  • package.json.npmrc・CI 設定・デザインシステムファイル変更時に docs/decisions.md 等の未更新を警告
  • コミットはブロックしない(exit 0)
  • README にセットアップ手順を追記

docs

  • docs/decisions.md: [010] CSS 変数移行、[011] pre-commit フックの決断を記録
  • SKILL.md: セクション 10 を CSS 変数アーキテクチャの説明に更新、warning カラー修正
  • CLAUDE.md: セキュリティ設定変更をドキュメント更新ルール表に追加

Test plan

  • npm run dev で開発サーバーが起動する
  • npm run build がエラーなく完了する
  • GS1 DataBar ページで各ツールが正常に動作する(バーコード生成・ダウンロード)
  • 警告カラーが適切なコントラストで表示される(JWTデコーダーの exp なし バッジ)
  • package.json だけをステージしてコミットすると pre-commit フックが警告を出す

🤖 Generated with Claude Code

fumtas1k and others added 6 commits April 12, 2026 13:58
- Replace module-level nextId counter with crypto.randomUUID()
  to avoid ID conflicts on StrictMode double-mount and hot reload
- Pass stable cardId prop to BarcodeCard for inputId (was index-based,
  which shifts when a card is removed)
- Compute gs1String once instead of calling buildBwipText twice
- Add missing radix to parseInt calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Gs1Databar.tsx: replace all hardcoded hex values with colors.* tokens
  from styles.ts, consistent with other tool components
- Extract focus ring handlers to focusRingOn/focusRingOff to eliminate
  repeated inline event handlers
- styles.ts: make micro an alias of caption (they were identical values)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SKILL.md:
- Fix --color-warning from #D97706 (amber-600, fails WCAG AA 4.5:1 on
  white at ~3.3:1) to #854D0E (amber-800) to match actual implementation
- Fix --color-warning-bg from #FFFBEB to #FEF3C7 to match styles.ts
- Add section 10: project-specific implementation patterns
  (colors.* tokens, typography constants, Tailwind vs inline style split,
  focusRing pattern)

CLAUDE.md:
- Add security config changes (.npmrc, CI) to doc update rules table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- global.css: add semantic CSS variable aliases (--color-text, --color-muted,
  --color-bg, --color-bg-surface, --color-bg-subtle, --color-border,
  --color-border-input, --color-error-text) in :root
- global.css: fix --color-warning (#D97706→#854D0E) and --color-warning-bg
  (#FFFBEB→#FEF3C7) to match accessible values
- styles.ts: colors.* values now reference var(--color-*) instead of hex
  literals — dark mode only needs .dark overrides in global.css
- CopyButton.tsx, JanCode.tsx: migrate hardcoded hex to colors.* tokens
- SKILL.md: update section 10 to reflect CSS variable architecture

Note: hex literals remain in bwip-js/JsBarcode renderer configs as those
libraries cannot resolve CSS variables.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
.githooks/pre-commit warns (without blocking) when:
- package.json changed → SPEC.md / docs/decisions.md not staged
- .npmrc changed → docs/decisions.md not staged
- .github/workflows/ changed → docs/decisions.md not staged
- src/styles/global.css or styles.ts changed → docs/decisions.md not staged
- new tool page added → README.md / SPEC.md / docs/decisions.md not staged

Activate with: git config core.hooksPath .githooks
README: add setup step for git hooks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hook

[010] Color tokens migrated to CSS variables for dark mode readiness
[011] pre-commit hook for doc update reminders

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying devtools with  Cloudflare Pages  Cloudflare Pages

Latest commit: a63ab14
Status: ✅  Deploy successful!
Preview URL: https://adb65d01.devtools-d9w.pages.dev
Branch Preview URL: https://develop.devtools-d9w.pages.dev

View logs

@fumtas1k fumtas1k self-assigned this Apr 12, 2026
@fumtas1k
fumtas1k merged commit a6b5fe4 into main Apr 12, 2026
2 checks passed
fumtas1k added a commit that referenced this pull request May 2, 2026
レビュー [nit] #6: 「他のツールへ広げるか否かは別 issue で議論」が issue
番号未記載で shared-agent-rules.md 6.4 章 (deferral 時は番号明記) に違反
していた。CSP gate 全 spec 展開の追跡として #234 を、cfworker 移行で
失われた未知キーワード等の検出能力を「スキーマ lint」として復活させる
追跡として #235 を、それぞれ該当箇所に引用追加。

レビュー [major] #2: Ajv strict 喪失の UX 後退に対し、UI 注記追加か追跡
issue 起票かの選択で issue 起票ルートを採用 (#235)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 2, 2026
…ト追加 (#233)

* fix(config-converter): スキーマ検証を @cfworker/json-schema へ差し替え CSP unsafe-eval 違反を解消

Cloudflare Pages 本番で「JSON Schema で検証する」が CSP `unsafe-eval`
拒否でエラーになっていた。Ajv 8.x はスキーマを `new Function()` で
JIT コンパイルする設計で、本番 CSP (script-src 'self' 'unsafe-inline')
と非互換。

interpreter 実装で eval / new Function を使わない @cfworker/json-schema
へ差し替え、CSP 緩和なしに同等以上の draft 4/7/2019-09/2020-12 対応を
得る。$schema URI から draft 検出(既定 draft-07)。formats は draft
規定の定義に従い ajv-formats なしで評価。

挙動差: 仕様準拠のため未知のキーワード (旧 strict:true 検出) は無視。
詳細・選定根拠は docs/decisions.md [061] を参照。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(csp): PRODUCTION_CSP を src/utils/csp.ts に集約し _headers と同期テスト追加

E2E ヘルパーから本番相当 CSP を再利用するため、_headers の CSP
文字列を TypeScript の定数 (PRODUCTION_CSP) として src/utils/csp.ts
にミラーし single source of truth とする。

src/utils/__tests__/headers.test.ts に「_headers の Content-Security-
Policy 値が PRODUCTION_CSP と完全一致する」アサーションを追加し、
片方だけ更新する事故を Vitest で即時検出する。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(e2e): 本番相当 CSP 注入ヘルパー applyProductionCsp と config-converter デグレ防止テスト追加

playwright.config.ts は npm run dev で起動し dev server は public/_headers
を解釈しないため、本番でしか効かない CSP 違反 (今回の Ajv unsafe-eval)
が CI 素通りしていた既知の穴を塞ぐ。

tests/e2e/helpers.ts に applyProductionCsp(page) を追加:
- page.route で HTML 文書のレスポンスに PRODUCTION_CSP を注入
- console error / pageerror から CSP 違反メッセージを収集し
  assertNoViolations() で test failure へ昇格

tests/e2e/config-converter.spec.ts に「本番相当 CSP 下でも検証成功
し違反が出ない」シナリオを追加。Ajv 時代に発生した本番限定不具合を
CI で確実に再現できることを実証。

射程は当初 config-converter のみ。他ツールへの拡大は別 issue で議論。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(decisions): [061] config-converter CSP unsafe-eval 修正と検知ゲート追加を記録

決断 A (Ajv → @cfworker/json-schema 差し替え) と B (E2E に本番相当
CSP を注入するリグレッション検知ゲート追加) の選定根拠と却下案
(unsafe-eval 緩和 / Ajv standalone / @hyperjump/json-schema /
wrangler pages dev / meta タグ) を整理。

[054] で「将来課題」とした dev/preview 非適用 CSP の検知穴を、
本決定で具体化して塞いだことを明記。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(decisions): [061] から #176 の過剰参照を削除

#176 は CSP `'unsafe-inline'` 削減の親 issue で、本件 (`'unsafe-eval'`
拒否による Ajv 不適合) とは別ディレクティブの話。直接の関係はないため
[061] の「関連 PR / issue」と「却下した選択肢」内の #176 への言及を削除し、
unsafe-eval 緩和却下の理由を「allow-list を緩める影響」に絞って書き直した。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(e2e): applyProductionCsp に陽性対照テストと dispose API + browser.newContext 必須を明示

レビュー [major] #1: applyProductionCsp が違反を実際に検知できる保証がない
点に対し、外部 origin の <script src> 注入で意図的に CSP 違反を発生させ
guard.violations が確実に増えることを確認するメタテストを追加。これを
追加する過程で、default の `page` / `context` test fixture では
page.route 介入が成立しない事象が発覚 (Astro dev server 経路で再現)。
従来 PR で追加したリグレッション防止テスト自体も実は CSP が効いておらず
cfworker が eval しないので偶然 green になっていた状態だった。

両テストを browser.newContext() 経由の新規コンテキストに切り替え、
applyProductionCsp が初回ナビゲーションから確実に介入するように修正。
helper の JSDoc にこの制約を明記し、同じ事故を踏まないようにする。

合わせてレビュー [minor]:
- CspGuard.dispose() を追加し、page.unroute / page.off で listener を解除
  できるようにする (将来 fixture 化したときの hook)
- 違反検出メッセージの正規表現が Chromium 固有である点を JSDoc 明記

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(schema-validator): 空 error 既定値と未対応 draft fallback 回帰防止テスト

レビュー [nit] #4: cfworker の OutputUnit.error が null/undefined だった
場合、UI 側の `<strong>{path}</strong>: {message}` が `/path: ` で右辺空に
崩れる。toLegacyError に既定値「検証失敗(詳細なし)」を入れて UX を安定化。

レビュー [minor] #3: detectDraft は未対応 draft URI (例: draft-06) を
silent に draft-07 へ fallback するが、現状テストで意図表明されていなかった
ため、将来仕様変更時の意図確認用として draft-06 入力に対する fallback
挙動の回帰防止テストを 1 本追加。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(decisions): [061] に follow-up issue #234 / #235 を追記

レビュー [nit] #6: 「他のツールへ広げるか否かは別 issue で議論」が issue
番号未記載で shared-agent-rules.md 6.4 章 (deferral 時は番号明記) に違反
していた。CSP gate 全 spec 展開の追跡として #234 を、cfworker 移行で
失われた未知キーワード等の検出能力を「スキーマ lint」として復活させる
追跡として #235 を、それぞれ該当箇所に引用追加。

レビュー [major] #2: Ajv strict 喪失の UX 後退に対し、UI 注記追加か追跡
issue 起票かの選択で issue 起票ルートを採用 (#235)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 3, 2026
レビュー指摘 #3 #4 への対応:

- shared-agent-rules.md 6.2: 「`origin/develop` 起点を必ず明示」の理由(PR #154/#181 既知問題)と playbook 1.1 章へのポインタを追加
- playbooks/e2e-validation.md 2.1: ステップ 0 のコマンド列が広すぎたので説明文を表外の引用ブロックへ移動
- playbooks/pr-creation.md 4: PR 作成コマンドの一時ファイルパス例に `$TMPDIR/pr_body.md` を併記(`/tmp/claude/` も併記、permissions allow/ask の理由を明示)

レビュー指摘 #1 (SSOT 明示) と #2 (参照チェッカ機械化) は別 issue で対応予定。
fumtas1k added a commit that referenced this pull request May 3, 2026
* docs(rules): playbooks/ と setup/ 配下にタスク手順書・環境セットアップを切り出す

shared-agent-rules.md の肥大化対策として、以下 4 ファイルを新設:
- docs/playbooks/pr-creation.md: ブランチ作成→検証→PR→マージの完全手順
- docs/playbooks/e2e-validation.md: E2E 実行手順・push 前チェックリスト・失敗判定
- docs/setup/plugins.md: Claude Code プラグイン install ガイド (Web silent fail / context7 403 / API キー)
- docs/setup/gemini-policy.md: Gemini security policy symlink セットアップ

「常時必読の規約」と「タスク開始時に読む手順書」を物理的に分離し、
セッション毎に必要な情報量を減らすのが狙い。

* docs(rules): CLAUDE.md / GEMINI.md / shared-agent-rules.md を新ファイル参照型に圧縮

肥大化していた常時ロード対象ファイルを以下の方針でスリム化:

- CLAUDE.md: 80→46 行。プラグイン install トラブル詳細を docs/setup/plugins.md へ移動
- GEMINI.md: 53→39 行。security policy symlink 手順を docs/setup/gemini-policy.md へ移動
- shared-agent-rules.md: 365→258 行。以下を移動:
  - 旧 3 章(E2E 実行手順)→ docs/playbooks/e2e-validation.md
  - 旧 6.2 / 6.2a(ブランチ作成詳細)と 3.2 親 push チェックリスト → docs/playbooks/pr-creation.md
  - 旧 8 章(UI 目視確認)→ docs/ui-conventions.md 3.1 章に統合
- 旧 10 章 → 9 章、旧 11 章 → 10 章、旧 12 章 → 11 章 に章番号を繰り上げ
- agent-lessons.md の章番号参照を新番号に追従

各章末尾に「詳細手順 → docs/playbooks/X.md」のポインタを残して双方向リンク化。

* docs(rules): PR #240 レビュー指摘の軽微対応(「なぜ」補足 / 表幅 / TMPDIR 例示)

レビュー指摘 #3 #4 への対応:

- shared-agent-rules.md 6.2: 「`origin/develop` 起点を必ず明示」の理由(PR #154/#181 既知問題)と playbook 1.1 章へのポインタを追加
- playbooks/e2e-validation.md 2.1: ステップ 0 のコマンド列が広すぎたので説明文を表外の引用ブロックへ移動
- playbooks/pr-creation.md 4: PR 作成コマンドの一時ファイルパス例に `$TMPDIR/pr_body.md` を併記(`/tmp/claude/` も併記、permissions allow/ask の理由を明示)

レビュー指摘 #1 (SSOT 明示) と #2 (参照チェッカ機械化) は別 issue で対応予定。
fumtas1k added a commit that referenced this pull request May 7, 2026
…ld-key DRY-up

#275 review feedback (#2 / #4) への対応:

- JwtDecoder.tsx: section-jwt-${variant} の template literal を
  SECTION_CLASSES const map 化。grep 性向上 + 同 PR 内の FIELD_CLASSES
  pattern との一貫性確保 (review #4)。

- global.css `.uuid-field-key`: caption (font-size 以外) と同値の 4 値を
  自前で持っていた self-contained 実装を、caption 継承 + font-size override
  に DRY-up。caption typography が将来変わったとき自動追従 (review #2)。

- UuidV7Generator.tsx: 上記の caption 継承に合わせ <span> の className を
  "text-muted uuid-field-key" → "caption text-muted uuid-field-key" に。

review #1 (.section-jwt-payload の hex token 化) は spec D2 に従い PR 6
cleanup へ deferr (decisions [067] 候補)。
review #3 (browser.newContext ラッパ helper 化) は別 issue 起票で
PR 5 前段 infra PR として対応予定。

ref: #275

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 7, 2026
…ne style 撤去 + #262 partial (#275)

* chore(spec): #176 B 案 PR 3 spec / plan / global.css foundation

Phase 0: spec / plan 配置 + global.css @layer components に
JwtDecoder + UuidV7Generator migration 用 class 16 件を追加。

追加 class:
- section-jwt-{header,payload,signature}
- jwt-json-{key,value}
- jwt-pre / accent-link
- text-warning / bg-warning-tint
- uuid-field-{ts,ver,rand-a,var,rand-b}
- uuid-field-{key,bits}

Phase 1 (sonnet 並列) で JwtDecoder / UuidV7Generator + uuid-v7 E2E
の migration を進める。

ref: docs/projects/issue-176-b-plan-progress.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(tools): #176 B 案 PR 3 — JwtDecoder.tsx inline style 撤去

Section component の accentColor prop を variant prop (header / payload /
signature の discriminated union) に変更。expBadge / sigBadge の style
オブジェクトを badgeClass 文字列に変更。<pre> typography を .jwt-pre
class に集約。checkbox accent-color を .accent-link class に置換。
import { bodyEmphasis, caption, colors } from '@/utils/styles' を削除。

ref: docs/superpowers/specs/2026-05-07-issue-176-b3-jwt-uuid-design.md §1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(tools): #176 B 案 PR 3 — UuidV7Generator.tsx inline style 撤去

FIELD_COLORS const を FIELD_CLASSES const に refactor し、ColoredUuid /
FieldBreakdownPanel の動的色を class 切替で表現。inline style 20 件を
@layer components の class + Tailwind utility に置換。
import { bodyEmphasis, caption, colors } from '@/utils/styles' を削除。

ref: docs/superpowers/specs/2026-05-07-issue-176-b3-jwt-uuid-design.md §2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(e2e): #176 B 案 PR 3 — uuid-v7 spec に applyProductionCsp gate 追加 (#262 partial)

PR 6 で style-src 'unsafe-inline' を削除した際の CSP 違反を能動検出する
ため、tests/e2e/uuid-v7.spec.ts の全 test を browser.newContext() pattern
に変更し applyProductionCsp(page) を goto 前に挿入。陽性対照 1 件追加
(script-src 違反で gate 動作確認、config-converter.spec.ts 既存 pattern 踏襲)。

ulid-generator 部分は PR 5 で対応して #262 close 予定。

ref: docs/superpowers/specs/2026-05-07-issue-176-b3-jwt-uuid-design.md §3
ref: #262

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(migration): MIGRATED_FILES に PR 3 対象 2 件追加

JwtDecoder.tsx / UuidV7Generator.tsx の inline style 撤去完了に
伴い progressive migration tracker に追加 (16 → 18 件)。

ref: docs/superpowers/specs/2026-05-07-issue-176-b3-jwt-uuid-design.md §5

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(tools,ui): #275 review 対応 — SECTION_CLASSES map 化 + uuid-field-key DRY-up

#275 review feedback (#2 / #4) への対応:

- JwtDecoder.tsx: section-jwt-${variant} の template literal を
  SECTION_CLASSES const map 化。grep 性向上 + 同 PR 内の FIELD_CLASSES
  pattern との一貫性確保 (review #4)。

- global.css `.uuid-field-key`: caption (font-size 以外) と同値の 4 値を
  自前で持っていた self-contained 実装を、caption 継承 + font-size override
  に DRY-up。caption typography が将来変わったとき自動追従 (review #2)。

- UuidV7Generator.tsx: 上記の caption 継承に合わせ <span> の className を
  "text-muted uuid-field-key" → "caption text-muted uuid-field-key" に。

review #1 (.section-jwt-payload の hex token 化) は spec D2 に従い PR 6
cleanup へ deferr (decisions [067] 候補)。
review #3 (browser.newContext ラッパ helper 化) は別 issue 起票で
PR 5 前段 infra PR として対応予定。

ref: #275

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(progress): #176 B 案 PR 3 (#275) の状態と follow-up を反映

PR #275 がまだ open のため merge 後の chore PR 待ちにすると
follow-up の persist が遅延する。本 PR 内で SoT を更新して
PR 5 着手時に確実に拾えるようにする。

更新内容:
- 進捗状況テーブル: PR 3 を 🔄 PR open + #275 link に変更、
  scope に "+ #262 partial" を追記
- 着手済 PR の prerequisite / 同梱 issue 履歴: PR 3 (#275) を新設
  - #262 (PR 内 partial、close は PR 5 で)
  - #276 (review 由来 follow-up、PR 5 前段 infra PR)
- follow-up issue 処理タイミング表: タイトルを PR 1〜3 に拡張、
  日付 2026-05-04 → 2026-05-07、#262 を "PR 5 で close" に更新、
  #276 を新規行追加
- PR 6 必須チェックリスト: follow-up リストに PR 3 由来 (#276) を追加、
  #262 description を partial 反映に更新

ref: #275
ref: #276
ref: #262

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 12, 2026
* feat(ui): StatusIcon / CloseIcon コンポーネントを追加

デバイス非依存の inline SVG アイコンコンポーネントを追加。
StatusIcon は success / error / warning の 3 variant を持ち、
CloseIcon は削除・閉じるボタン用の ✕ アイコン。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(tools): CharCount の絵文字を StatusIcon に置換

✅ ❌ ⚠ を inline SVG (StatusIcon) に置き換え。
改行コード混在の ⚠ も warning variant の StatusIcon に変更し、
aria-hidden ラップなしで SR に読まれていた問題を解消。
ユニットテストのセレクタから ❌ を除去 (sr-only「不可」でマッチ)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(tools): ConfigConverter / VerifyTab の絵文字を StatusIcon に置換

ConfigConverter のスキーマ検証成功 ✅ と、
VerifyTab のチケット検証結果 ✓ ✕ を StatusIcon に置き換え。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(tools): GenerateTab / Gs1Databar の記号を SVG に置換

GenerateTab のアコーディオン ▲▼ を chevron SVG (rotate-180 で切替) に、
行削除 ✕ を CloseIcon に置き換え。Gs1Databar の AI フィールド削除 ✕ も同様。
E2E セレクタを ▼ テキスト依存から role+name 取得に変更。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(pages): char-count.astro の説明文中の ❌ をテキストに置換

インライン絵文字 ❌ を <strong class="text-error">不可</strong> に変更。
React SVG コンポーネントのマウントが不要な説明文はテキスト表現で統一。
E2E セレクタを ✅ 絵文字依存から dt+dd ロケーターに更新。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(char-count): EncRow の inline-flex wrapper を削除し行高肥大を修正

inline-flex items-center で wrap すると baseline 計算が通常の inline span と
異なり dd.caption の line box が 23.8px を超えて拡張される問題を修正。

StatusIcon は inline-block align-middle を持つため、wrapper を外しても
inline 配置でテキスト中央揃えは維持される。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(vrt): visual regression baseline を CI Linux runner で再生成

* fix(ui): StatusIcon warning dot を degenerate line から circle に + Icon unit test 追加

PR #407 レビュー指摘 #1 / #4 対応:

- StatusIcon.tsx の warning variant 底辺ドットを 0 長 line + stroke
  round cap 依存から `<circle r="1.25" fill="currentColor" />` に置換。
  PDF export / 古い WebKit でゼロ長 segment を skip する portability
  リスクを排除し意図も明示化
- StatusIcon / CloseIcon の unit test を新規追加。variant 別 SVG 切替
  (polyline / line×2 / path+line+circle) / aria-hidden / size prop /
  className 継承の regression check で既存 UI コンポーネント test 規約と
  整合

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(ui): GenerateTab の inline chevron SVG を ChevronIcon コンポーネントに抽出

PR #407 レビュー指摘 #2 対応:

GenerateTab.tsx の accordion chevron (inline SVG 13 行) を
`src/components/ui/ChevronIcon.tsx` に抽出。`open` prop で 180° 回転を
表現する API に揃え、StatusIcon / CloseIcon と粒度を一致させた
「アイコン規約整理 PR」の一貫性を確保する。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(a11y): VerifyTab / ConfigConverter の冗長 sr-only 接頭辞を削除

PR #407 レビュー指摘 #3 対応:

StatusIcon の後に置いた `<span className="sr-only">期限切れ: </span>` 等が
直後の可視テキスト「有効期限切れ」と二重読み上げ
(「期限切れ: 有効期限切れ」) を起こす a11y 退化を解消。
StatusIcon 自身は aria-hidden で読み上げ対象外、可視テキストが意味を
完結しているため sr-only 接頭辞を削除する。

対象:
- VerifyTab.tsx: 「有効: / 期限切れ: / 無効: 」3 箇所
- ConfigConverter.tsx: 「成功: 」1 箇所

CharCount.tsx は「対応 10 byte」のように後続バイト数を含む意味があり
sr-only テキストが必要なため変更しない (パターン分岐の理由は
本 PR の design rationale)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(ui): ChevronIcon の unit test を追加

PR #407 再レビュー指摘の任意 observation 対応:

`ChevronIcon` は前回指摘 #4 (StatusIcon / CloseIcon の test 追加) の
対象外だったが、後発で抽出した分 `open` prop による rotate 切り替えロジックを
持つため同等の unit test を追加し UI コンポーネント test 規約と完全に揃える。

7 ケース:
- polyline 描画 / aria-hidden / currentColor
- open=true で rotate-180 + transition-transform 付与
- open=false (default) で rotate-180 なし (transition は維持)
- size prop (default 14)
- className 継承

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
fumtas1k added a commit that referenced this pull request May 12, 2026
PR #415 LGTM レビュー指摘の 2 件 + 設計記録 [078] を本 PR で巻き取り:

- package.json `pretest:e2e:dev` の port kill 範囲を 4322 のみ → 4321,4322 に
  拡張。`test:e2e:dev` は webServer 配列で preview (4321) も起動するため、
  stale process 4321 で EADDRINUSE する従来リスクを 1 行で消す
  (memory feedback_pretest_kill_workflow に類例あり、defense in depth)
- docs/decisions.md [078]: dev mode 2 層検知の trade-off を明文化
  - なぜ 2 層必要か (React 18 attribute mismatch の production silent
    recovery 仕様)
  - なぜ CI step を 1 step 統合せず 2 step 分離したか (failure granularity
    優先、+15s overhead 許容)
  - 却下した代替案 (dev のみ統一 / per-project webServer / 1 step 統合)
  - test-gates checklist #2 の empirical 検証 (Gs1Databar revert で fail
    昇格確認)
  archaeology を [077] と並べて辿れるよう [078] エントリ化

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 12, 2026
…415)

* test(e2e): #414 dev mode 経路の Playwright project + CI step を追加

PR #408 の hydration meta spec は production build (`npm run preview`) 経路で
動作するため、**attribute mismatch は React 18 の silent recovery で console
に出ず catch できない**。本番 Cloudflare Pages を実機検証して console error
0 件 (https://devtools-d9w.pages.dev/tools/gs1-databar/) で実証済み。

dev mode (React dev build) では attribute mismatch も
`A tree hydrated but some attributes of the server rendered HTML didn't match
the client properties.` を console.error として発火するため、astro dev server
(port 4322) を併走させ、専用 Playwright project (`hydration-dev`) で catch する
2 層検知 infra を構築する。

- playwright.config.ts: webServer を配列化 (preview port 4321 + dev port 4322
  を並列起動)、`hydration-dev` project (testMatch: hydration-check-dev*.spec.ts、
  baseURL override) を追加。既存 e2e project は dev mode spec を testIgnore で
  除外し相互独立
- package.json: `test:e2e:dev` / `pretest:e2e:dev` (port 4322 cleanup) script
- .github/workflows/test.yml: e2e job 内で `npm run test:e2e` 後に dev mode
  hydration check step を追加 (build artefact 再利用、dev server overhead +30-60s)

検知 spec / fixture は後続 commit で追加。本 commit 単独では新 project が
empty で実行されるのみで既存 CI に影響なし。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(fixtures): attribute mismatch hydration fixture を追加 (#414)

陽性対照テスト用 fixture component / page。SSR では
`data-rendered="server"` を、CSR (client hydration) では
`data-rendered="client"` を出す `<div>` を `client:load` で mount する
ことで <div> 要素の attribute mismatch を意図的に再現する。

React 18 はこの attribute mismatch を dev mode のみ
`A tree hydrated but some attributes of the server rendered HTML didn't match
the client properties.` として console.error する (production では silent
recovery)。PR #408 の text content mismatch fixture
(HydrationMismatch.tsx) は別ルートで production minified error を出すが、
attribute mismatch はこのルートに乗らないため別 fixture が必要。

prod URL `/test-fixtures/attr-hydration-broken` は
public/_redirects (#408 由来) の `/test-fixtures/* /404 404` で本番のみ
404 化される。noindex meta + tools.ts 非登録の二重防御も継承。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(e2e): #414 dev mode hydration check 陰性+陽性対照 spec を追加

- hydration-check-dev.spec.ts (陰性対照): visual-regression-pages.ts の全
  PAGES を 1 context 内で巡回し、`watchHydrationWarnings` で warning 0 件
  を assert。dev React は attribute mismatch も
  `A tree hydrated but some attributes...` を console.error するため
  PR #408 production 経路で漏れていた検知漏れを補完
- hydration-check-dev.gate.spec.ts (陽性対照、test-gates skill 要件):
  attribute mismatch fixture (`/test-fixtures/attr-hydration-broken`) を訪問
  し、warning > 0 を `expect.poll` で観測。listener や regex を破壊すると
  fail に昇格して検知能力ゼロでの green を防ぐ。`console.log('[hydration-dev-gate]
  captured: ...')` で artifact log に経路情報を残す

検証 (test-gates checklist #2 充足):
旧 Gs1Databar の `crypto.randomUUID()` 版に陰性対照を当てると
`gtin-input-<UUID_SERVER>` vs `gtin-input-<UUID_CLIENT>` の attribute diff
が捕捉されて fail に昇格することをローカルで実機確認済 (検証後 git restore
で develop の `useId()` 版に復元)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(decisions): [078] PR #415 レビュー指摘対応 — pretest port 修正 + 設計記録

PR #415 LGTM レビュー指摘の 2 件 + 設計記録 [078] を本 PR で巻き取り:

- package.json `pretest:e2e:dev` の port kill 範囲を 4322 のみ → 4321,4322 に
  拡張。`test:e2e:dev` は webServer 配列で preview (4321) も起動するため、
  stale process 4321 で EADDRINUSE する従来リスクを 1 行で消す
  (memory feedback_pretest_kill_workflow に類例あり、defense in depth)
- docs/decisions.md [078]: dev mode 2 層検知の trade-off を明文化
  - なぜ 2 層必要か (React 18 attribute mismatch の production silent
    recovery 仕様)
  - なぜ CI step を 1 step 統合せず 2 step 分離したか (failure granularity
    優先、+15s overhead 許容)
  - 却下した代替案 (dev のみ統一 / per-project webServer / 1 step 統合)
  - test-gates checklist #2 の empirical 検証 (Gs1Databar revert で fail
    昇格確認)
  archaeology を [077] と並べて辿れるよう [078] エントリ化

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 21, 2026
… を反映

レビュー対応:
- should-fix #1: 陽性対照 #1 の `descenderApprox = 5` ハードコードを `Math.ceil(fontSize * 0.28)` の em 比に変更し fontSize 変更時の silent regression 穴を塞ぐ。コメントを「spec 下限の行動的検証」と「固定値 assertion」の責務分担として明確化
- should-fix #2: decisions [084] 「結果・トレードオフ」節に dark mode UI での白背景 rect 視覚調和トレードオフを 1 行追加 (decode 信頼性優先の意図明文化)
- nice #1: `result.indexOf('>')` を `result.match(/<svg[^>]*>/)` に変更し SVG 属性値内に `>` を含むケースの誤切断 silent regression を防ぐ
- nice #2: 白背景 rect に `data-role="bg"` 属性付与。E2E paddingwidth 陽性対照 filter を `fill === 'white'` から `data-role === 'bg'` に変更し、将来 bwip-js が `fill="white"` decorative rect を出すと誤除外する fragility を低減。unit test 陽性対照も併せて `data-role="bg"` を assert
- nice #3: decisions [083] 「明確に否定された」結論行に `[084]` への forward reference を追加し過去 ADR を単独で読んだ保守者の誤認を防止
- nice #4: `quietZone = 9` (= 3X) を選択した経験則 (spec 下限 1X はマージン薄、12X 以上は視覚的に分離、3X は spec 3 倍マージンで頑健) をコメントとして残置

unit 42 件 (gs1-databar) / 全体 1310 件 / astro check 0 errors / format clean。
陽性対照の検知能力は全件維持または強化 (em 比化で fontSize 連動破綻、data-role anchor で identifier 強化)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 28, 2026
入力 JSON が不正な間にクエリが入っていると評価できず結果欄が無言でブランクに
なっていた。クエリ欄のヒントを文脈依存にし「入力 JSON を修正するとクエリを
実行できます」と案内する(設計書の意図に合わせる)。回帰 E2E を併設。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 31, 2026
レビュー指摘対応。

- OutputField の className/statusClassName/textareaClassName の 3 つの
  エスケープハッチを単一の fill prop に置換し、内部 DOM 3 層へのレイアウト
  クラス付与をコンポーネント内にカプセル化(#2)
- fill 時は手動リサイズ(resize-y)と h-full の競合を避けるため resize-none を
  強制し managed height を保証(#3)
- エラー表示で入力カラムが伸びても items-stretch で左右カラム高さが揃うことを
  検証する E2E を追加。旧実装(items-start)で fail する陽性対照を確認済み(#4)
- 既存「デスクトップ幅で揃う」テストの許容値に根拠コメントを付与(#5)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant