alpha-visualizer 0.1.0__tar.gz

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 (132) hide show
  1. alpha_visualizer-0.1.0/.agents/skills/source-command-audit-licenses/SKILL.md +180 -0
  2. alpha_visualizer-0.1.0/.agents/skills/source-command-pre-release/SKILL.md +78 -0
  3. alpha_visualizer-0.1.0/.claude/commands/audit-licenses.md +176 -0
  4. alpha_visualizer-0.1.0/.claude/commands/pre-release.md +73 -0
  5. alpha_visualizer-0.1.0/.codex/hooks.json +15 -0
  6. alpha_visualizer-0.1.0/.github/workflows/ci.yml +30 -0
  7. alpha_visualizer-0.1.0/.github/workflows/release.yml +39 -0
  8. alpha_visualizer-0.1.0/.gitignore +25 -0
  9. alpha_visualizer-0.1.0/AGENTS.md +1 -0
  10. alpha_visualizer-0.1.0/CLAUDE.md +152 -0
  11. alpha_visualizer-0.1.0/PKG-INFO +66 -0
  12. alpha_visualizer-0.1.0/README.md +39 -0
  13. alpha_visualizer-0.1.0/THIRDPARTY_LICENSES.txt +1767 -0
  14. alpha_visualizer-0.1.0/frontend/.gitignore +24 -0
  15. alpha_visualizer-0.1.0/frontend/.npmrc +1 -0
  16. alpha_visualizer-0.1.0/frontend/README.md +92 -0
  17. alpha_visualizer-0.1.0/frontend/THIRDPARTY_FONTS.md +48 -0
  18. alpha_visualizer-0.1.0/frontend/eslint.config.js +22 -0
  19. alpha_visualizer-0.1.0/frontend/index.html +32 -0
  20. alpha_visualizer-0.1.0/frontend/package-lock.json +3403 -0
  21. alpha_visualizer-0.1.0/frontend/package.json +45 -0
  22. alpha_visualizer-0.1.0/frontend/public/favicon.svg +1 -0
  23. alpha_visualizer-0.1.0/frontend/public/icons.svg +24 -0
  24. alpha_visualizer-0.1.0/frontend/src/api/client.ts +83 -0
  25. alpha_visualizer-0.1.0/frontend/src/api/types.ts +141 -0
  26. alpha_visualizer-0.1.0/frontend/src/charts/visx/CompareEquityV.tsx +350 -0
  27. alpha_visualizer-0.1.0/frontend/src/charts/visx/DrawdownChartV.tsx +162 -0
  28. alpha_visualizer-0.1.0/frontend/src/charts/visx/EquityChartV.tsx +442 -0
  29. alpha_visualizer-0.1.0/frontend/src/charts/visx/MonthlyHeatmapV.tsx +142 -0
  30. alpha_visualizer-0.1.0/frontend/src/charts/visx/Sparkline.tsx +77 -0
  31. alpha_visualizer-0.1.0/frontend/src/components/DetailToolbar.tsx +87 -0
  32. alpha_visualizer-0.1.0/frontend/src/components/MetricsSummaryBarV2.tsx +201 -0
  33. alpha_visualizer-0.1.0/frontend/src/components/RootLayout.tsx +5 -0
  34. alpha_visualizer-0.1.0/frontend/src/components/SettingsToggles.tsx +135 -0
  35. alpha_visualizer-0.1.0/frontend/src/components/StrategyHero.tsx +120 -0
  36. alpha_visualizer-0.1.0/frontend/src/components/browser/CompareFloatingBar.tsx +124 -0
  37. alpha_visualizer-0.1.0/frontend/src/components/browser/FilterBar.tsx +206 -0
  38. alpha_visualizer-0.1.0/frontend/src/components/browser/GroupByToggle.tsx +76 -0
  39. alpha_visualizer-0.1.0/frontend/src/components/browser/Heroline.tsx +103 -0
  40. alpha_visualizer-0.1.0/frontend/src/components/browser/RunHistoryTab.tsx +61 -0
  41. alpha_visualizer-0.1.0/frontend/src/components/browser/SavedViews.tsx +153 -0
  42. alpha_visualizer-0.1.0/frontend/src/components/browser/StrategySlidePanel.tsx +283 -0
  43. alpha_visualizer-0.1.0/frontend/src/components/browser/StrategyTable.tsx +529 -0
  44. alpha_visualizer-0.1.0/frontend/src/components/browser/SymbolAtlas.tsx +189 -0
  45. alpha_visualizer-0.1.0/frontend/src/components/browser/SymbolCard.tsx +180 -0
  46. alpha_visualizer-0.1.0/frontend/src/components/charts/DrawdownDetailChart.tsx +217 -0
  47. alpha_visualizer-0.1.0/frontend/src/components/charts/MAEMFEScatter.tsx +321 -0
  48. alpha_visualizer-0.1.0/frontend/src/components/charts/MonteCarloChart.tsx +358 -0
  49. alpha_visualizer-0.1.0/frontend/src/components/charts/ReturnDistributionChart.tsx +243 -0
  50. alpha_visualizer-0.1.0/frontend/src/components/charts/RollingMetricsChart.tsx +308 -0
  51. alpha_visualizer-0.1.0/frontend/src/components/charts/VaRChart.tsx +207 -0
  52. alpha_visualizer-0.1.0/frontend/src/components/charts/WFOTimeline.tsx +379 -0
  53. alpha_visualizer-0.1.0/frontend/src/components/charts/WeekdayPerformanceChart.tsx +219 -0
  54. alpha_visualizer-0.1.0/frontend/src/components/metrics/CompareTable.tsx +233 -0
  55. alpha_visualizer-0.1.0/frontend/src/components/metrics/ISOOSMetrics.tsx +176 -0
  56. alpha_visualizer-0.1.0/frontend/src/components/metrics/MetricsGrid.tsx +154 -0
  57. alpha_visualizer-0.1.0/frontend/src/components/metrics/SignalQualityBadge.tsx +146 -0
  58. alpha_visualizer-0.1.0/frontend/src/components/nav.ts +25 -0
  59. alpha_visualizer-0.1.0/frontend/src/components/trades/TradeTable.tsx +194 -0
  60. alpha_visualizer-0.1.0/frontend/src/constants/metricDefinitions.ts +48 -0
  61. alpha_visualizer-0.1.0/frontend/src/contexts/DashboardContext.tsx +42 -0
  62. alpha_visualizer-0.1.0/frontend/src/contexts/dashboardConstants.ts +6 -0
  63. alpha_visualizer-0.1.0/frontend/src/design/a11y.css +41 -0
  64. alpha_visualizer-0.1.0/frontend/src/design/primitives/Button.tsx +91 -0
  65. alpha_visualizer-0.1.0/frontend/src/design/primitives/Card.tsx +40 -0
  66. alpha_visualizer-0.1.0/frontend/src/design/primitives/Chip.tsx +57 -0
  67. alpha_visualizer-0.1.0/frontend/src/design/primitives/Divider.tsx +23 -0
  68. alpha_visualizer-0.1.0/frontend/src/design/primitives/KeyValue.tsx +55 -0
  69. alpha_visualizer-0.1.0/frontend/src/design/primitives/Pill.tsx +30 -0
  70. alpha_visualizer-0.1.0/frontend/src/design/primitives/SectionHeader.tsx +90 -0
  71. alpha_visualizer-0.1.0/frontend/src/design/primitives/Stat.tsx +103 -0
  72. alpha_visualizer-0.1.0/frontend/src/design/primitives/TabBar.tsx +68 -0
  73. alpha_visualizer-0.1.0/frontend/src/design/primitives/Toolbar.tsx +37 -0
  74. alpha_visualizer-0.1.0/frontend/src/design/primitives/index.ts +10 -0
  75. alpha_visualizer-0.1.0/frontend/src/design/tokens.css +179 -0
  76. alpha_visualizer-0.1.0/frontend/src/design/useChartTheme.ts +90 -0
  77. alpha_visualizer-0.1.0/frontend/src/hooks/useBacktestData.ts +149 -0
  78. alpha_visualizer-0.1.0/frontend/src/hooks/useScrollRestoration.ts +41 -0
  79. alpha_visualizer-0.1.0/frontend/src/hooks/useSparklineCache.ts +52 -0
  80. alpha_visualizer-0.1.0/frontend/src/hooks/useStrategyList.ts +243 -0
  81. alpha_visualizer-0.1.0/frontend/src/hooks/useSymbolStats.ts +78 -0
  82. alpha_visualizer-0.1.0/frontend/src/hooks/useTheme.ts +93 -0
  83. alpha_visualizer-0.1.0/frontend/src/i18n/strings.ts +9 -0
  84. alpha_visualizer-0.1.0/frontend/src/lib/assetClass.ts +70 -0
  85. alpha_visualizer-0.1.0/frontend/src/main.tsx +26 -0
  86. alpha_visualizer-0.1.0/frontend/src/mock/btData.ts +234 -0
  87. alpha_visualizer-0.1.0/frontend/src/pages/BrowsePage.tsx +201 -0
  88. alpha_visualizer-0.1.0/frontend/src/pages/ComparePage.tsx +209 -0
  89. alpha_visualizer-0.1.0/frontend/src/pages/DetailPage.tsx +214 -0
  90. alpha_visualizer-0.1.0/frontend/src/router.tsx +17 -0
  91. alpha_visualizer-0.1.0/frontend/src/screens/BacktestScreen.tsx +164 -0
  92. alpha_visualizer-0.1.0/frontend/src/screens/CompareScreen.tsx +292 -0
  93. alpha_visualizer-0.1.0/frontend/src/screens/ISOOSScreen.tsx +140 -0
  94. alpha_visualizer-0.1.0/frontend/src/screens/WFOScreen.tsx +113 -0
  95. alpha_visualizer-0.1.0/frontend/tsconfig.app.json +35 -0
  96. alpha_visualizer-0.1.0/frontend/tsconfig.json +7 -0
  97. alpha_visualizer-0.1.0/frontend/tsconfig.node.json +24 -0
  98. alpha_visualizer-0.1.0/frontend/vite.config.ts +30 -0
  99. alpha_visualizer-0.1.0/pyproject.toml +83 -0
  100. alpha_visualizer-0.1.0/src/alpha_visualizer/__init__.py +3 -0
  101. alpha_visualizer-0.1.0/src/alpha_visualizer/app.py +73 -0
  102. alpha_visualizer-0.1.0/src/alpha_visualizer/cli.py +66 -0
  103. alpha_visualizer-0.1.0/src/alpha_visualizer/db.py +61 -0
  104. alpha_visualizer-0.1.0/src/alpha_visualizer/forge_config.py +133 -0
  105. alpha_visualizer-0.1.0/src/alpha_visualizer/routers/__init__.py +0 -0
  106. alpha_visualizer-0.1.0/src/alpha_visualizer/routers/ideas.py +57 -0
  107. alpha_visualizer-0.1.0/src/alpha_visualizer/routers/results.py +352 -0
  108. alpha_visualizer-0.1.0/src/alpha_visualizer/routers/strategies.py +272 -0
  109. alpha_visualizer-0.1.0/src/alpha_visualizer/routers/wfo.py +126 -0
  110. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/index-16K3BxVS.css +1 -0
  111. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/index-dB6krL5g.js +11 -0
  112. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/index-dB6krL5g.js.map +1 -0
  113. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-400-normal-BLrFJfvD.woff +0 -0
  114. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-400-normal-iW8qmuJY.woff2 +0 -0
  115. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-500-normal-BFXNXuvF.woff2 +0 -0
  116. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-500-normal-pobXraBK.woff +0 -0
  117. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-600-normal-BgSTtRxb.woff2 +0 -0
  118. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-600-normal-D7bG6gX1.woff +0 -0
  119. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  120. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  121. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/source-serif-4-latin-600-normal-DMD1h6_f.woff +0 -0
  122. alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/source-serif-4-latin-600-normal-DouSKlru.woff2 +0 -0
  123. alpha_visualizer-0.1.0/src/alpha_visualizer/static/favicon.svg +1 -0
  124. alpha_visualizer-0.1.0/src/alpha_visualizer/static/icons.svg +24 -0
  125. alpha_visualizer-0.1.0/src/alpha_visualizer/static/index.html +33 -0
  126. alpha_visualizer-0.1.0/tests/__init__.py +0 -0
  127. alpha_visualizer-0.1.0/tests/conftest.py +17 -0
  128. alpha_visualizer-0.1.0/tests/test_app.py +102 -0
  129. alpha_visualizer-0.1.0/tests/test_cli.py +29 -0
  130. alpha_visualizer-0.1.0/tests/test_forge_config.py +174 -0
  131. alpha_visualizer-0.1.0/tests/test_routers.py +381 -0
  132. alpha_visualizer-0.1.0/uv.lock +1004 -0
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: "source-command-audit-licenses"
3
+ description: "サードパーティライセンスを監査し THIRDPARTY_LICENSES.txt を生成する"
4
+ ---
5
+
6
+ # source-command-audit-licenses
7
+
8
+ Use this skill when the user asks to run the migrated source command `audit-licenses`.
9
+
10
+ ## Command Template
11
+
12
+ # audit-licenses コマンド
13
+
14
+ Python 依存パッケージとフロントエンド(frontend/)の全サードパーティライセンスを監査し、
15
+ GPL/AGPL 混入がないことを確認した上で `THIRDPARTY_LICENSES.txt` をプロジェクトルートに生成する。
16
+ リリース前に必ず実行すること。
17
+
18
+ ## 使い方
19
+
20
+ ```
21
+ /audit-licenses
22
+ ```
23
+
24
+ ## 実行手順
25
+
26
+ ### Step 1: Python側のライセンス監査
27
+
28
+ 1. `pip-licenses` を仮想環境にインストールする。
29
+
30
+ ```bash
31
+ cd alpha-visualizer
32
+ uv pip install pip-licenses
33
+ ```
34
+
35
+ 2. 全パッケージのライセンスを取得する。
36
+
37
+ ```bash
38
+ uv run pip-licenses --format=markdown --order=license
39
+ ```
40
+
41
+ 3. 出力を確認し、以下のいずれかが**ランタイム依存**として存在する場合は**直ちに中断**してユーザーに報告する。
42
+
43
+ - ライセンス名に `GPL` または `AGPL` を含むパッケージ
44
+ - ただし以下は**開発専用(dev)**のため除外して判定する:
45
+ - `pytest`, `ruff`, `httpx`(devツール)
46
+ - `pip-licenses`, `prettytable`(監査ツール)
47
+
48
+ 4. LGPL はランタイム混入でも即中断ではなく、
49
+ 後述の THIRDPARTY_LICENSES.txt にLGPL告知を記載する形で続行する。
50
+
51
+ ### Step 2: フロントエンド側のライセンス監査
52
+
53
+ 1. visualizer ディレクトリで `license-checker` を実行する。
54
+
55
+ ```bash
56
+ cd alpha-visualizer/frontend
57
+ npx license-checker --summary
58
+ ```
59
+
60
+ 2. GPL または AGPL を含むパッケージを発見した場合は**直ちに中断**してユーザーに報告する。
61
+ (`frontend@0.0.0` の `UNLICENSED` はプロジェクト自身のため無視する)
62
+
63
+ ### Step 3: THIRDPARTY_LICENSES.txt の生成
64
+
65
+ Step 1・Step 2 で問題がなければ以下を実行する。
66
+
67
+ 1. Python ライセンス情報を JSON で取得する。
68
+
69
+ ```bash
70
+ cd alpha-visualizer
71
+ uv run pip-licenses --format=json --with-license-file --no-license-path > /tmp/py-licenses.json
72
+ ```
73
+
74
+ 2. フロントエンドのライセンス情報を JSON で取得する。
75
+
76
+ ```bash
77
+ cd alpha-visualizer/frontend
78
+ npx license-checker --json --out /tmp/fe-licenses.json
79
+ ```
80
+
81
+ 3. 以下の Python スクリプトを実行して `THIRDPARTY_LICENSES.txt` を生成する。
82
+
83
+ ```python
84
+ import json
85
+ from datetime import date
86
+
87
+ DEV_ONLY = {
88
+ "alpha-visualizer",
89
+ "pytest", "ruff", "httpx",
90
+ "pip-licenses", "prettytable",
91
+ }
92
+
93
+ with open("/tmp/py-licenses.json") as f:
94
+ py_data = json.load(f)
95
+ with open("/tmp/fe-licenses.json") as f:
96
+ fe_data = json.load(f)
97
+
98
+ py_pkgs = [p for p in sorted(py_data, key=lambda x: x["Name"].lower())
99
+ if p["Name"] not in DEV_ONLY]
100
+ fe_pkgs = [(pkg, info) for pkg, info in sorted(fe_data.items())
101
+ if not pkg.startswith("frontend@")]
102
+
103
+ SEP = "=" * 80
104
+ lines = [
105
+ SEP, "THIRDPARTY_LICENSES.txt", SEP,
106
+ f"Generated: {date.today().isoformat()}", "",
107
+ "This product includes third-party software components listed below.",
108
+ "These components are subject to their respective licenses.", "",
109
+ ]
110
+
111
+ lgpl_pkgs = [p for p in py_pkgs if "LGPL" in p["License"] or "lgpl" in p["License"].lower()]
112
+ if lgpl_pkgs:
113
+ lines += [
114
+ "IMPORTANT LGPL NOTICE", "-" * 40,
115
+ "This distribution includes the following LGPL-licensed libraries:",
116
+ ]
117
+ for p in lgpl_pkgs:
118
+ lines.append(f" - {p['Name']} ({p['License']})")
119
+ lines += [
120
+ "",
121
+ "In compliance with LGPL-3.0, the source code of these libraries is",
122
+ "available at their respective repositories listed in this file.",
123
+ "Users may replace these libraries with modified versions by rebuilding",
124
+ "from source. Contact us if you require object files for relinking.",
125
+ "",
126
+ ]
127
+
128
+ lines += [SEP, "", "SECTION 1: PYTHON DEPENDENCIES", SEP,
129
+ f"Total: {len(py_pkgs)} packages", ""]
130
+ for p in py_pkgs:
131
+ lines += [f" {p['Name']} {p['Version']}", f" License: {p['License']}"]
132
+ text = p.get("LicenseText", "").strip()
133
+ if text and text not in ("UNKNOWN", ""):
134
+ lines.append(" License Text:")
135
+ for line in text.splitlines()[:30]:
136
+ lines.append(f" {line}")
137
+ if len(text.splitlines()) > 30:
138
+ lines.append(" [... full text available at PyPI ...]")
139
+ lines.append("")
140
+
141
+ lines += [SEP, "", "SECTION 2: FRONTEND DEPENDENCIES (Vite + React)", SEP,
142
+ f"Total: {len(fe_pkgs)} packages", ""]
143
+ for pkg_ver, info in fe_pkgs:
144
+ lines += [f" {pkg_ver}", f" License: {info.get('licenses', '')}"]
145
+ repo = info.get("repository", "")
146
+ if repo:
147
+ lines.append(f" Repository: {repo}")
148
+ lines.append("")
149
+ lines.append(SEP)
150
+
151
+ output = "\n".join(lines)
152
+ with open("THIRDPARTY_LICENSES.txt", "w") as f:
153
+ f.write(output)
154
+ print(f"Generated THIRDPARTY_LICENSES.txt ({len(output)} bytes, Python: {len(py_pkgs)}, Frontend: {len(fe_pkgs)})")
155
+ ```
156
+
157
+ ```bash
158
+ cd alpha-visualizer
159
+ uv run python -c "<上記スクリプト>"
160
+ ```
161
+
162
+ 4. 生成されたファイルの先頭を表示して内容を確認する。
163
+
164
+ ```bash
165
+ head -30 THIRDPARTY_LICENSES.txt
166
+ ```
167
+
168
+ ## 完了後の確認事項
169
+
170
+ - [ ] `THIRDPARTY_LICENSES.txt` がプロジェクトルートに生成されていること
171
+ - [ ] GPL/AGPL パッケージが**ランタイム依存**に含まれていないこと
172
+ - [ ] LGPL パッケージがある場合、ファイル先頭に LGPL 告知が記載されていること
173
+ - [ ] ファイルを `git add THIRDPARTY_LICENSES.txt` してリリースコミットに含めること
174
+
175
+ ## 注意
176
+
177
+ - Python の仮想環境(`.venv`)が存在し `uv sync` 済みであることを前提とする。
178
+ - `pip-licenses` と `prettytable` はこのコマンド専用の監査ツールであり、`pyproject.toml` の
179
+ 依存には含めない(`uv pip install` で都度インストールする)。
180
+ - フロントエンドの `node_modules/` が存在しない場合は `npm install` を先に実行すること。
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: "source-command-pre-release"
3
+ description: "テスト・Lint 検証から PyPI リリースまでのフローを実行する"
4
+ ---
5
+
6
+ # source-command-pre-release
7
+
8
+ Use this skill when the user asks to run the migrated source command `pre-release`.
9
+
10
+ ## Command Template
11
+
12
+ # pre-release コマンド
13
+
14
+ alpha-visualizer のリリース前にテスト・Lint を実行して検証し、問題なければバージョンを上げて PyPI に公開する。
15
+
16
+ ## 使い方
17
+
18
+ ```
19
+ /pre-release [patch|minor|major]
20
+ ```
21
+
22
+ 引数を省略した場合は `patch` として扱う。
23
+
24
+ ## 実行手順
25
+
26
+ 1. **作業ディレクトリの確認**
27
+
28
+ alpha-visualizer リポジトリのルートにいること、かつ `main` ブランチにいることを確認する。
29
+
30
+ ```bash
31
+ git branch --show-current
32
+ git status
33
+ ```
34
+
35
+ 未コミットの変更があれば中断してユーザーに確認を求める。
36
+
37
+ 2. **テスト・Lint 検証**
38
+
39
+ ```bash
40
+ uv run ruff check src/ tests/
41
+ uv run pytest tests/ -q
42
+ ```
43
+
44
+ いずれかが失敗した場合は中断してエラー内容をユーザーに報告する。
45
+
46
+ 3. **バージョン確認**
47
+
48
+ 現在のバージョンと、バンプ後のバージョンをユーザーに提示して確認を求める。
49
+
50
+ ```bash
51
+ grep '^version' pyproject.toml
52
+ ```
53
+
54
+ バンプ後のバージョンを計算して提示する(例: `0.1.0` → patch → `0.1.1`)。
55
+
56
+ 4. **リリース実行**
57
+
58
+ ユーザーの承認を得てから実行する。
59
+
60
+ ```bash
61
+ # バージョンを bump してコミット・タグ
62
+ uv run bump-my-version bump ${PART}
63
+
64
+ # PyPI に公開
65
+ uv build
66
+ uv publish
67
+
68
+ # タグを push
69
+ git push --tags
70
+ git push
71
+ ```
72
+
73
+ ## 注意
74
+
75
+ - `git push --tags` と `uv publish` は不可逆な操作のため、実行前に必ずユーザーの承認を取ること。
76
+ - `bump-my-version` が必要(`uv sync --all-groups` で導入済みのはず)。
77
+ - PyPI 認証情報(`UV_PUBLISH_TOKEN` 等)が設定されていること。
78
+ - リリース前に `/audit-licenses` を実行して `THIRDPARTY_LICENSES.txt` を最新化すること。
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: audit-licenses
3
+ description: サードパーティライセンスを監査し THIRDPARTY_LICENSES.txt を生成する
4
+ command: true
5
+ ---
6
+
7
+ # audit-licenses コマンド
8
+
9
+ Python 依存パッケージとフロントエンド(frontend/)の全サードパーティライセンスを監査し、
10
+ GPL/AGPL 混入がないことを確認した上で `THIRDPARTY_LICENSES.txt` をプロジェクトルートに生成する。
11
+ リリース前に必ず実行すること。
12
+
13
+ ## 使い方
14
+
15
+ ```
16
+ /audit-licenses
17
+ ```
18
+
19
+ ## 実行手順
20
+
21
+ ### Step 1: Python側のライセンス監査
22
+
23
+ 1. `pip-licenses` を仮想環境にインストールする。
24
+
25
+ ```bash
26
+ cd alpha-visualizer
27
+ uv pip install pip-licenses
28
+ ```
29
+
30
+ 2. 全パッケージのライセンスを取得する。
31
+
32
+ ```bash
33
+ uv run pip-licenses --format=markdown --order=license
34
+ ```
35
+
36
+ 3. 出力を確認し、以下のいずれかが**ランタイム依存**として存在する場合は**直ちに中断**してユーザーに報告する。
37
+
38
+ - ライセンス名に `GPL` または `AGPL` を含むパッケージ
39
+ - ただし以下は**開発専用(dev)**のため除外して判定する:
40
+ - `pytest`, `ruff`, `httpx`(devツール)
41
+ - `pip-licenses`, `prettytable`(監査ツール)
42
+
43
+ 4. LGPL はランタイム混入でも即中断ではなく、
44
+ 後述の THIRDPARTY_LICENSES.txt にLGPL告知を記載する形で続行する。
45
+
46
+ ### Step 2: フロントエンド側のライセンス監査
47
+
48
+ 1. visualizer ディレクトリで `license-checker` を実行する。
49
+
50
+ ```bash
51
+ cd alpha-visualizer/frontend
52
+ npx license-checker --summary
53
+ ```
54
+
55
+ 2. GPL または AGPL を含むパッケージを発見した場合は**直ちに中断**してユーザーに報告する。
56
+ (`frontend@0.0.0` の `UNLICENSED` はプロジェクト自身のため無視する)
57
+
58
+ ### Step 3: THIRDPARTY_LICENSES.txt の生成
59
+
60
+ Step 1・Step 2 で問題がなければ以下を実行する。
61
+
62
+ 1. Python ライセンス情報を JSON で取得する。
63
+
64
+ ```bash
65
+ cd alpha-visualizer
66
+ uv run pip-licenses --format=json --with-license-file --no-license-path > /tmp/py-licenses.json
67
+ ```
68
+
69
+ 2. フロントエンドのライセンス情報を JSON で取得する。
70
+
71
+ ```bash
72
+ cd alpha-visualizer/frontend
73
+ npx license-checker --json --out /tmp/fe-licenses.json
74
+ ```
75
+
76
+ 3. 以下の Python スクリプトを実行して `THIRDPARTY_LICENSES.txt` を生成する。
77
+
78
+ ```python
79
+ import json
80
+ from datetime import date
81
+
82
+ DEV_ONLY = {
83
+ "alpha-visualizer",
84
+ "pytest", "ruff", "httpx",
85
+ "pip-licenses", "prettytable",
86
+ }
87
+
88
+ with open("/tmp/py-licenses.json") as f:
89
+ py_data = json.load(f)
90
+ with open("/tmp/fe-licenses.json") as f:
91
+ fe_data = json.load(f)
92
+
93
+ py_pkgs = [p for p in sorted(py_data, key=lambda x: x["Name"].lower())
94
+ if p["Name"] not in DEV_ONLY]
95
+ fe_pkgs = [(pkg, info) for pkg, info in sorted(fe_data.items())
96
+ if not pkg.startswith("frontend@")]
97
+
98
+ SEP = "=" * 80
99
+ lines = [
100
+ SEP, "THIRDPARTY_LICENSES.txt", SEP,
101
+ f"Generated: {date.today().isoformat()}", "",
102
+ "This product includes third-party software components listed below.",
103
+ "These components are subject to their respective licenses.", "",
104
+ ]
105
+
106
+ # LGPL告知(該当パッケージが存在する場合)
107
+ lgpl_pkgs = [p for p in py_pkgs if "LGPL" in p["License"] or "lgpl" in p["License"].lower()]
108
+ if lgpl_pkgs:
109
+ lines += [
110
+ "IMPORTANT LGPL NOTICE", "-" * 40,
111
+ "This distribution includes the following LGPL-licensed libraries:",
112
+ ]
113
+ for p in lgpl_pkgs:
114
+ lines.append(f" - {p['Name']} ({p['License']})")
115
+ lines += [
116
+ "",
117
+ "In compliance with LGPL-3.0, the source code of these libraries is",
118
+ "available at their respective repositories listed in this file.",
119
+ "Users may replace these libraries with modified versions by rebuilding",
120
+ "from source. Contact us if you require object files for relinking.",
121
+ "",
122
+ ]
123
+
124
+ lines += [SEP, "", "SECTION 1: PYTHON DEPENDENCIES", SEP,
125
+ f"Total: {len(py_pkgs)} packages", ""]
126
+ for p in py_pkgs:
127
+ lines += [f" {p['Name']} {p['Version']}", f" License: {p['License']}"]
128
+ text = p.get("LicenseText", "").strip()
129
+ if text and text not in ("UNKNOWN", ""):
130
+ lines.append(" License Text:")
131
+ for line in text.splitlines()[:30]:
132
+ lines.append(f" {line}")
133
+ if len(text.splitlines()) > 30:
134
+ lines.append(" [... full text available at PyPI ...]")
135
+ lines.append("")
136
+
137
+ lines += [SEP, "", "SECTION 2: FRONTEND DEPENDENCIES (Vite + React)", SEP,
138
+ f"Total: {len(fe_pkgs)} packages", ""]
139
+ for pkg_ver, info in fe_pkgs:
140
+ lines += [f" {pkg_ver}", f" License: {info.get('licenses', '')}"]
141
+ repo = info.get("repository", "")
142
+ if repo:
143
+ lines.append(f" Repository: {repo}")
144
+ lines.append("")
145
+ lines.append(SEP)
146
+
147
+ output = "\n".join(lines)
148
+ with open("THIRDPARTY_LICENSES.txt", "w") as f:
149
+ f.write(output)
150
+ print(f"Generated THIRDPARTY_LICENSES.txt ({len(output)} bytes, Python: {len(py_pkgs)}, Frontend: {len(fe_pkgs)})")
151
+ ```
152
+
153
+ ```bash
154
+ cd alpha-visualizer
155
+ uv run python -c "<上記スクリプト>"
156
+ ```
157
+
158
+ 4. 生成されたファイルの先頭を表示して内容を確認する。
159
+
160
+ ```bash
161
+ head -30 THIRDPARTY_LICENSES.txt
162
+ ```
163
+
164
+ ## 完了後の確認事項
165
+
166
+ - [ ] `THIRDPARTY_LICENSES.txt` がプロジェクトルートに生成されていること
167
+ - [ ] GPL/AGPL パッケージが**ランタイム依存**に含まれていないこと
168
+ - [ ] LGPL パッケージがある場合、ファイル先頭に LGPL 告知が記載されていること
169
+ - [ ] ファイルを `git add THIRDPARTY_LICENSES.txt` してリリースコミットに含めること
170
+
171
+ ## 注意
172
+
173
+ - Python の仮想環境(`.venv`)が存在し `uv sync` 済みであることを前提とする。
174
+ - `pip-licenses` と `prettytable` はこのコマンド専用の監査ツールであり、`pyproject.toml` の
175
+ 依存には含めない(`uv pip install` で都度インストールする)。
176
+ - フロントエンドの `node_modules/` が存在しない場合は `npm install` を先に実行すること。
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: pre-release
3
+ description: テスト・Lint 検証から PyPI リリースまでのフローを実行する
4
+ command: true
5
+ ---
6
+
7
+ # pre-release コマンド
8
+
9
+ alpha-visualizer のリリース前にテスト・Lint を実行して検証し、問題なければバージョンを上げて PyPI に公開する。
10
+
11
+ ## 使い方
12
+
13
+ ```
14
+ /pre-release [patch|minor|major]
15
+ ```
16
+
17
+ 引数を省略した場合は `patch` として扱う。
18
+
19
+ ## 実行手順
20
+
21
+ 1. **作業ディレクトリの確認**
22
+
23
+ alpha-visualizer リポジトリのルートにいること、かつ `main` ブランチにいることを確認する。
24
+
25
+ ```bash
26
+ git branch --show-current
27
+ git status
28
+ ```
29
+
30
+ 未コミットの変更があれば中断してユーザーに確認を求める。
31
+
32
+ 2. **テスト・Lint 検証**
33
+
34
+ ```bash
35
+ uv run ruff check src/ tests/
36
+ uv run pytest tests/ -q
37
+ ```
38
+
39
+ いずれかが失敗した場合は中断してエラー内容をユーザーに報告する。
40
+
41
+ 3. **バージョン確認**
42
+
43
+ 現在のバージョンと、バンプ後のバージョンをユーザーに提示して確認を求める。
44
+
45
+ ```bash
46
+ grep '^version' pyproject.toml
47
+ ```
48
+
49
+ バンプ後のバージョンを計算して提示する(例: `0.1.0` → patch → `0.1.1`)。
50
+
51
+ 4. **リリース実行**
52
+
53
+ ユーザーの承認を得てから実行する。
54
+
55
+ ```bash
56
+ # バージョンを bump してコミット・タグ
57
+ uv run bump-my-version bump ${PART}
58
+
59
+ # PyPI に公開
60
+ uv build
61
+ uv publish
62
+
63
+ # タグを push
64
+ git push --tags
65
+ git push
66
+ ```
67
+
68
+ ## 注意
69
+
70
+ - `git push --tags` と `uv publish` は不可逆な操作のため、実行前に必ずユーザーの承認を取ること。
71
+ - `bump-my-version` が必要(`uv sync --all-groups` で導入済みのはず)。
72
+ - PyPI 認証情報(`UV_PUBLISH_TOKEN` 等)が設定されていること。
73
+ - リリース前に `/audit-licenses` を実行して `THIRDPARTY_LICENSES.txt` を最新化すること。
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Edit|Write",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "FILE=\"${CLAUDE_TOOL_INPUT_FILE_PATH}\"; [[ \"$FILE\" == *.py ]] && cd \"$(git rev-parse --show-toplevel)\" && uv run ruff check --fix \"$FILE\" 2>/dev/null || true"
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint-and-test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v4
17
+ with:
18
+ version: "latest"
19
+
20
+ - name: Set up Python
21
+ run: uv python install 3.12
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --all-extras
25
+
26
+ - name: Lint (ruff)
27
+ run: uv run ruff check src/ tests/
28
+
29
+ - name: Test (pytest)
30
+ run: uv run pytest tests/ -q
@@ -0,0 +1,39 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ contents: read # private repo で actions/checkout が読み取れるようにする
14
+ id-token: write # PyPI Trusted Publisher 用
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v4
20
+ with:
21
+ version: "latest"
22
+
23
+ - name: Set up Python
24
+ run: uv python install 3.12
25
+
26
+ - name: Install dependencies
27
+ run: uv sync --all-extras
28
+
29
+ - name: Lint (ruff)
30
+ run: uv run ruff check src/ tests/
31
+
32
+ - name: Test (pytest)
33
+ run: uv run pytest tests/ -q
34
+
35
+ - name: Build
36
+ run: uv build
37
+
38
+ - name: Publish to PyPI
39
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,25 @@
1
+ # Python
2
+ .venv/
3
+ __pycache__/
4
+ *.pyc
5
+ *.pyo
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ dist/
9
+ *.egg-info/
10
+ .env
11
+ .env.*
12
+ .coverage
13
+ htmlcov/
14
+ coverage.xml
15
+
16
+ # SQLite
17
+ *.db
18
+ *.db-wal
19
+ *.db-shm
20
+
21
+ # Frontend
22
+ frontend/node_modules/
23
+ frontend/.tsbuildinfo
24
+
25
+ src/alpha_forge/
@@ -0,0 +1 @@
1
+ CLAUDE.md