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.
- alpha_visualizer-0.1.0/.agents/skills/source-command-audit-licenses/SKILL.md +180 -0
- alpha_visualizer-0.1.0/.agents/skills/source-command-pre-release/SKILL.md +78 -0
- alpha_visualizer-0.1.0/.claude/commands/audit-licenses.md +176 -0
- alpha_visualizer-0.1.0/.claude/commands/pre-release.md +73 -0
- alpha_visualizer-0.1.0/.codex/hooks.json +15 -0
- alpha_visualizer-0.1.0/.github/workflows/ci.yml +30 -0
- alpha_visualizer-0.1.0/.github/workflows/release.yml +39 -0
- alpha_visualizer-0.1.0/.gitignore +25 -0
- alpha_visualizer-0.1.0/AGENTS.md +1 -0
- alpha_visualizer-0.1.0/CLAUDE.md +152 -0
- alpha_visualizer-0.1.0/PKG-INFO +66 -0
- alpha_visualizer-0.1.0/README.md +39 -0
- alpha_visualizer-0.1.0/THIRDPARTY_LICENSES.txt +1767 -0
- alpha_visualizer-0.1.0/frontend/.gitignore +24 -0
- alpha_visualizer-0.1.0/frontend/.npmrc +1 -0
- alpha_visualizer-0.1.0/frontend/README.md +92 -0
- alpha_visualizer-0.1.0/frontend/THIRDPARTY_FONTS.md +48 -0
- alpha_visualizer-0.1.0/frontend/eslint.config.js +22 -0
- alpha_visualizer-0.1.0/frontend/index.html +32 -0
- alpha_visualizer-0.1.0/frontend/package-lock.json +3403 -0
- alpha_visualizer-0.1.0/frontend/package.json +45 -0
- alpha_visualizer-0.1.0/frontend/public/favicon.svg +1 -0
- alpha_visualizer-0.1.0/frontend/public/icons.svg +24 -0
- alpha_visualizer-0.1.0/frontend/src/api/client.ts +83 -0
- alpha_visualizer-0.1.0/frontend/src/api/types.ts +141 -0
- alpha_visualizer-0.1.0/frontend/src/charts/visx/CompareEquityV.tsx +350 -0
- alpha_visualizer-0.1.0/frontend/src/charts/visx/DrawdownChartV.tsx +162 -0
- alpha_visualizer-0.1.0/frontend/src/charts/visx/EquityChartV.tsx +442 -0
- alpha_visualizer-0.1.0/frontend/src/charts/visx/MonthlyHeatmapV.tsx +142 -0
- alpha_visualizer-0.1.0/frontend/src/charts/visx/Sparkline.tsx +77 -0
- alpha_visualizer-0.1.0/frontend/src/components/DetailToolbar.tsx +87 -0
- alpha_visualizer-0.1.0/frontend/src/components/MetricsSummaryBarV2.tsx +201 -0
- alpha_visualizer-0.1.0/frontend/src/components/RootLayout.tsx +5 -0
- alpha_visualizer-0.1.0/frontend/src/components/SettingsToggles.tsx +135 -0
- alpha_visualizer-0.1.0/frontend/src/components/StrategyHero.tsx +120 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/CompareFloatingBar.tsx +124 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/FilterBar.tsx +206 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/GroupByToggle.tsx +76 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/Heroline.tsx +103 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/RunHistoryTab.tsx +61 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/SavedViews.tsx +153 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/StrategySlidePanel.tsx +283 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/StrategyTable.tsx +529 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/SymbolAtlas.tsx +189 -0
- alpha_visualizer-0.1.0/frontend/src/components/browser/SymbolCard.tsx +180 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/DrawdownDetailChart.tsx +217 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/MAEMFEScatter.tsx +321 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/MonteCarloChart.tsx +358 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/ReturnDistributionChart.tsx +243 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/RollingMetricsChart.tsx +308 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/VaRChart.tsx +207 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/WFOTimeline.tsx +379 -0
- alpha_visualizer-0.1.0/frontend/src/components/charts/WeekdayPerformanceChart.tsx +219 -0
- alpha_visualizer-0.1.0/frontend/src/components/metrics/CompareTable.tsx +233 -0
- alpha_visualizer-0.1.0/frontend/src/components/metrics/ISOOSMetrics.tsx +176 -0
- alpha_visualizer-0.1.0/frontend/src/components/metrics/MetricsGrid.tsx +154 -0
- alpha_visualizer-0.1.0/frontend/src/components/metrics/SignalQualityBadge.tsx +146 -0
- alpha_visualizer-0.1.0/frontend/src/components/nav.ts +25 -0
- alpha_visualizer-0.1.0/frontend/src/components/trades/TradeTable.tsx +194 -0
- alpha_visualizer-0.1.0/frontend/src/constants/metricDefinitions.ts +48 -0
- alpha_visualizer-0.1.0/frontend/src/contexts/DashboardContext.tsx +42 -0
- alpha_visualizer-0.1.0/frontend/src/contexts/dashboardConstants.ts +6 -0
- alpha_visualizer-0.1.0/frontend/src/design/a11y.css +41 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/Button.tsx +91 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/Card.tsx +40 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/Chip.tsx +57 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/Divider.tsx +23 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/KeyValue.tsx +55 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/Pill.tsx +30 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/SectionHeader.tsx +90 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/Stat.tsx +103 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/TabBar.tsx +68 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/Toolbar.tsx +37 -0
- alpha_visualizer-0.1.0/frontend/src/design/primitives/index.ts +10 -0
- alpha_visualizer-0.1.0/frontend/src/design/tokens.css +179 -0
- alpha_visualizer-0.1.0/frontend/src/design/useChartTheme.ts +90 -0
- alpha_visualizer-0.1.0/frontend/src/hooks/useBacktestData.ts +149 -0
- alpha_visualizer-0.1.0/frontend/src/hooks/useScrollRestoration.ts +41 -0
- alpha_visualizer-0.1.0/frontend/src/hooks/useSparklineCache.ts +52 -0
- alpha_visualizer-0.1.0/frontend/src/hooks/useStrategyList.ts +243 -0
- alpha_visualizer-0.1.0/frontend/src/hooks/useSymbolStats.ts +78 -0
- alpha_visualizer-0.1.0/frontend/src/hooks/useTheme.ts +93 -0
- alpha_visualizer-0.1.0/frontend/src/i18n/strings.ts +9 -0
- alpha_visualizer-0.1.0/frontend/src/lib/assetClass.ts +70 -0
- alpha_visualizer-0.1.0/frontend/src/main.tsx +26 -0
- alpha_visualizer-0.1.0/frontend/src/mock/btData.ts +234 -0
- alpha_visualizer-0.1.0/frontend/src/pages/BrowsePage.tsx +201 -0
- alpha_visualizer-0.1.0/frontend/src/pages/ComparePage.tsx +209 -0
- alpha_visualizer-0.1.0/frontend/src/pages/DetailPage.tsx +214 -0
- alpha_visualizer-0.1.0/frontend/src/router.tsx +17 -0
- alpha_visualizer-0.1.0/frontend/src/screens/BacktestScreen.tsx +164 -0
- alpha_visualizer-0.1.0/frontend/src/screens/CompareScreen.tsx +292 -0
- alpha_visualizer-0.1.0/frontend/src/screens/ISOOSScreen.tsx +140 -0
- alpha_visualizer-0.1.0/frontend/src/screens/WFOScreen.tsx +113 -0
- alpha_visualizer-0.1.0/frontend/tsconfig.app.json +35 -0
- alpha_visualizer-0.1.0/frontend/tsconfig.json +7 -0
- alpha_visualizer-0.1.0/frontend/tsconfig.node.json +24 -0
- alpha_visualizer-0.1.0/frontend/vite.config.ts +30 -0
- alpha_visualizer-0.1.0/pyproject.toml +83 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/__init__.py +3 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/app.py +73 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/cli.py +66 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/db.py +61 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/forge_config.py +133 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/routers/__init__.py +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/routers/ideas.py +57 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/routers/results.py +352 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/routers/strategies.py +272 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/routers/wfo.py +126 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/index-16K3BxVS.css +1 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/index-dB6krL5g.js +11 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/index-dB6krL5g.js.map +1 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-400-normal-BLrFJfvD.woff +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-400-normal-iW8qmuJY.woff2 +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-500-normal-BFXNXuvF.woff2 +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-500-normal-pobXraBK.woff +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-600-normal-BgSTtRxb.woff2 +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/inter-tight-latin-600-normal-D7bG6gX1.woff +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/source-serif-4-latin-600-normal-DMD1h6_f.woff +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/assets/source-serif-4-latin-600-normal-DouSKlru.woff2 +0 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/favicon.svg +1 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/icons.svg +24 -0
- alpha_visualizer-0.1.0/src/alpha_visualizer/static/index.html +33 -0
- alpha_visualizer-0.1.0/tests/__init__.py +0 -0
- alpha_visualizer-0.1.0/tests/conftest.py +17 -0
- alpha_visualizer-0.1.0/tests/test_app.py +102 -0
- alpha_visualizer-0.1.0/tests/test_cli.py +29 -0
- alpha_visualizer-0.1.0/tests/test_forge_config.py +174 -0
- alpha_visualizer-0.1.0/tests/test_routers.py +381 -0
- 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
|