toolost-uploader 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 (45) hide show
  1. toolost_uploader-0.1.0/LICENSE +21 -0
  2. toolost_uploader-0.1.0/MANIFEST.in +11 -0
  3. toolost_uploader-0.1.0/PKG-INFO +248 -0
  4. toolost_uploader-0.1.0/README.md +221 -0
  5. toolost_uploader-0.1.0/docs/schemas/manifest-v1.schema.json +62 -0
  6. toolost_uploader-0.1.0/docs/schemas/validate-result-v1.schema.json +23 -0
  7. toolost_uploader-0.1.0/pyproject.toml +45 -0
  8. toolost_uploader-0.1.0/setup.cfg +4 -0
  9. toolost_uploader-0.1.0/tests/test_approval.py +110 -0
  10. toolost_uploader-0.1.0/tests/test_browser.py +114 -0
  11. toolost_uploader-0.1.0/tests/test_cli.py +197 -0
  12. toolost_uploader-0.1.0/tests/test_fake_flow.py +105 -0
  13. toolost_uploader-0.1.0/tests/test_fake_ui.py +186 -0
  14. toolost_uploader-0.1.0/tests/test_fake_upload.py +172 -0
  15. toolost_uploader-0.1.0/tests/test_fake_workflow.py +155 -0
  16. toolost_uploader-0.1.0/tests/test_gated_upload.py +116 -0
  17. toolost_uploader-0.1.0/tests/test_gather.py +50 -0
  18. toolost_uploader-0.1.0/tests/test_journal.py +197 -0
  19. toolost_uploader-0.1.0/tests/test_live_draft.py +289 -0
  20. toolost_uploader-0.1.0/tests/test_live_recovery.py +452 -0
  21. toolost_uploader-0.1.0/tests/test_packaging.py +81 -0
  22. toolost_uploader-0.1.0/tests/test_read_only.py +86 -0
  23. toolost_uploader-0.1.0/tests/test_storage.py +321 -0
  24. toolost_uploader-0.1.0/tests/test_validate.py +220 -0
  25. toolost_uploader-0.1.0/toolost_uploader/__init__.py +3 -0
  26. toolost_uploader-0.1.0/toolost_uploader/__main__.py +3 -0
  27. toolost_uploader-0.1.0/toolost_uploader/approval.py +116 -0
  28. toolost_uploader-0.1.0/toolost_uploader/browser.py +253 -0
  29. toolost_uploader-0.1.0/toolost_uploader/cli.py +333 -0
  30. toolost_uploader-0.1.0/toolost_uploader/fake_flow.py +63 -0
  31. toolost_uploader-0.1.0/toolost_uploader/fake_ui.py +166 -0
  32. toolost_uploader-0.1.0/toolost_uploader/fake_upload.py +146 -0
  33. toolost_uploader-0.1.0/toolost_uploader/fake_workflow.py +160 -0
  34. toolost_uploader-0.1.0/toolost_uploader/journal.py +171 -0
  35. toolost_uploader-0.1.0/toolost_uploader/live_draft.py +468 -0
  36. toolost_uploader-0.1.0/toolost_uploader/live_journal.py +129 -0
  37. toolost_uploader-0.1.0/toolost_uploader/read_only.py +126 -0
  38. toolost_uploader-0.1.0/toolost_uploader/storage.py +282 -0
  39. toolost_uploader-0.1.0/toolost_uploader/validation.py +241 -0
  40. toolost_uploader-0.1.0/toolost_uploader.egg-info/PKG-INFO +248 -0
  41. toolost_uploader-0.1.0/toolost_uploader.egg-info/SOURCES.txt +43 -0
  42. toolost_uploader-0.1.0/toolost_uploader.egg-info/dependency_links.txt +1 -0
  43. toolost_uploader-0.1.0/toolost_uploader.egg-info/entry_points.txt +2 -0
  44. toolost_uploader-0.1.0/toolost_uploader.egg-info/requires.txt +6 -0
  45. toolost_uploader-0.1.0/toolost_uploader.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gunamaya / KiriminAja
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ include docs/schemas/*.json
5
+
6
+ recursive-include toolost_uploader *.py
7
+
8
+ prune .local
9
+ prune .venv
10
+ exclude .gitignore
11
+ global-exclude *.py[cod] __pycache__ *.so
@@ -0,0 +1,248 @@
1
+ Metadata-Version: 2.4
2
+ Name: toolost-uploader
3
+ Version: 0.1.0
4
+ Summary: CLI and Playwright automation tool for Too Lost music release manifests
5
+ Author-email: Gunamaya <developer@kiriminaja.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/gunamaya/toolost-uploader
8
+ Project-URL: Repository, https://github.com/gunamaya/toolost-uploader
9
+ Project-URL: Issues, https://github.com/gunamaya/toolost-uploader/issues
10
+ Keywords: too-lost,music-distribution,uploader,playwright,automation
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Multimedia :: Sound/Audio
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: playwright<2,>=1.40.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: build<2,>=1.2.2; extra == "dev"
24
+ Requires-Dist: twine<6,>=5.0.0; extra == "dev"
25
+ Requires-Dist: jsonschema<5,>=4.26; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # Toolost Uploader
29
+
30
+ CLI & Playwright Automation Tool untuk manajemen dan upload draft rilis [Too Lost](https://toolost.com) berbasis manifest JSON.
31
+
32
+ [![PyPI version](https://img.shields.io/badge/version-0.1.0-blue.svg)](https://pypi.org/project/toolost-uploader/)
33
+ [![Python versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://www.python.org/)
34
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
35
+ [![Tests](https://img.shields.io/badge/tests-171%20passed-brightgreen.svg)](#pengujian--pengembangan)
36
+
37
+ ---
38
+
39
+ ## Fitur Utama
40
+
41
+ - **Validasi Manifest Offline**: Memvalidasi metadata rilis (Single & Album), resolusi artwork (3000×3000px), format audio (MP3/WAV/FLAC), dan kecocokan hash integritas berkas (SHA-256) tanpa membuka jaringan atau browser.
42
+ - **Sesi Browser Mandiri & Aman**: Membuka Google Chrome biasa di profil lokal terisolasi (`.local/profiles/<alias>`) agar operator dapat login manual dengan aman tanpa menyimpan password/cookie mentah di kode repo.
43
+ - **Auto-Bootup & Readiness Check**: Diagnosa otomatis ketersediaan binary Chrome, status lock profil, port CDP (Chrome DevTools Protocol loopback), dan verifikasi sesi login aktif Too Lost terhadap `--expected-account`.
44
+ - **Eksekutor Playwright Single & Multi-Track Album**: Mengotomatisasi pemilihan tipe rilis, pengisian judul, upload & encoding artwork, multi-track audio, penataan urutan track, pengisian metadata AI per-track, hingga eksekusi simpan perubahan (*Save Changes*).
45
+ - **Safety First (Draft-Only Guard)**: Eksekusi dibatasi secara ketat hanya sampai penyimpanan draft (`--draft-only`). Tool ini **tidak pernah** menekan tombol Publish atau memicu distribusi rilis.
46
+ - **Desain Integrasi Subprocess**: Format keluaran stdout JSON murni yang deterministik dan aliran log progres real-time ke stderr, sangat ramah untuk integrasi aplikasi induk seperti [yt-to-flowmusic](docs/INTEGRATION-PLAN.md).
47
+
48
+ ---
49
+
50
+ ## Instalasi
51
+
52
+ ### Dari PyPI (Rekomendasi)
53
+
54
+ ```sh
55
+ pip install toolost-uploader
56
+ playwright install chromium
57
+ ```
58
+
59
+ ### Dari Source / Git
60
+
61
+ ```sh
62
+ git clone https://github.com/gunamaya/toolost-uploader.git
63
+ cd toolost-uploader
64
+ python3 -m venv .venv
65
+ source .venv/bin/activate
66
+ pip install -e .
67
+ playwright install chromium
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Panduan Penggunaan Cepat
73
+
74
+ Alur kerja umum terdiri dari 4 langkah berurutan:
75
+
76
+ ```mermaid
77
+ flowchart LR
78
+ A["1. Validasi Manifest<br/>(toolost validate)"] --> B["2. Setup Browser Login<br/>(toolost setup)"]
79
+ B --> C["3. Cek Kesiapan<br/>(toolost check)"]
80
+ C --> D["4. Upload Simpan Draft<br/>(toolost upload --draft-only)"]
81
+ ```
82
+
83
+ ### 1. Validasi Manifest Rilis (Offline)
84
+
85
+ Periksa integritas manifest JSON dan kecocokan hash SHA-256 berkas lokal:
86
+
87
+ ```sh
88
+ toolost validate path/to/manifest.json --json
89
+ ```
90
+
91
+ ### 2. Setup Sesi Browser (Login Manual Operator)
92
+
93
+ Buka browser Chrome lokal untuk login manual ke portal Too Lost. Sesi login akan disimpan secara privat di folder profil lokal:
94
+
95
+ ```sh
96
+ toolost setup --profile production
97
+ ```
98
+ *Tutup jendela Chrome setelah selesai login.*
99
+
100
+ ### 3. Diagnosa Kesiapan Lingkungan (Readiness Check)
101
+
102
+ Pastikan Google Chrome, port CDP, dan sesi akun siap:
103
+
104
+ ```sh
105
+ toolost check --profile production --expected-account 422512 --auto-bootup --json
106
+ ```
107
+
108
+ Contoh keluaran JSON (`exit code 0`):
109
+ ```json
110
+ {
111
+ "status": "ready",
112
+ "chrome_binary": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
113
+ "profile_dir": "/path/to/.local/profiles/production",
114
+ "cdp_url": "http://127.0.0.1:9437",
115
+ "auth": {
116
+ "status": "authenticated",
117
+ "account_id": "422512"
118
+ }
119
+ }
120
+ ```
121
+
122
+ ### 4. Unggah & Simpan Draft Rilis
123
+
124
+ Jalankan otomatisasi upload Playwright. Port CDP akan otomatis di-bootup bila belum aktif:
125
+
126
+ ```sh
127
+ toolost upload path/to/manifest.json \
128
+ --draft-only \
129
+ --profile production \
130
+ --expected-account 422512 \
131
+ --approve-draft \
132
+ --accept-ui-date \
133
+ --verbose \
134
+ --json
135
+ ```
136
+
137
+ Contoh keluaran JSON sukses:
138
+ ```json
139
+ {
140
+ "status": "draft_saved_subset",
141
+ "run_id": "20261026-154000-album-test",
142
+ "draft_id": "2004317",
143
+ "warnings": [
144
+ "Tanggal UI diwarisi; bukan release_date manifest terverifikasi.",
145
+ "Remote track identity dan rights/services belum diverifikasi; bukan siap distribusi."
146
+ ]
147
+ }
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Spesifikasi Manifest JSON (Schema v1)
153
+
154
+ Contoh manifest untuk rilis Album multi-track:
155
+
156
+ ```json
157
+ {
158
+ "schema_version": 1,
159
+ "release_id": "album-project-001",
160
+ "release_type": "album",
161
+ "title": "Album Eksperimental FlowMusic",
162
+ "release_date": "2026-11-01",
163
+ "artwork": {
164
+ "path": "/path/to/artwork-3000x3000.png",
165
+ "sha256": "338ca5ab7fb090dfa5b6cdc8fd6c68f2f8afa939266e412d85ee35187b275de6"
166
+ },
167
+ "tracks": [
168
+ {
169
+ "track_id": "track-01",
170
+ "title": "Terangnya Belum Pulang",
171
+ "audio": {
172
+ "path": "/path/to/track-01.mp3",
173
+ "sha256": "53431441811b965acc69664ec4e2dcf47d5765c2ddc483f4daf49ded30a7214d"
174
+ },
175
+ "ai_assisted": true
176
+ },
177
+ {
178
+ "track_id": "track-02",
179
+ "title": "Sungai Teh Susu",
180
+ "audio": {
181
+ "path": "/path/to/track-02.mp3",
182
+ "sha256": "4278102d0dcc1ba4e1886ba518552c1a974a8f88679536a021b3896eaecf61f1"
183
+ },
184
+ "ai_assisted": true
185
+ }
186
+ ]
187
+ }
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Referensi Kode Keluar (Exit Codes)
193
+
194
+ | Exit Code | Status JSON | Makna & Tindakan Penanganan |
195
+ |---|---|---|
196
+ | **`0`** | `valid`, `ready`, `draft_saved_subset` | Eksekusi sukses. Payload JSON memuat informasi rilis / kesiapan. |
197
+ | **`2`** | `invalid_input`, `login_required`, `account_mismatch` | Argumen salah, hash aset tidak cocok, atau sesi login perlu diperbarui melalui `toolost setup`. |
198
+ | **`4`** | `reconciliation_required` | Operasi dihentikan aman (*fail-stop*). Periksa status browser atau koneksi. Hindari melakukan *retry* buta. |
199
+ | **`5`** | Error I/O / OS | File tidak ditemukan atau binary Chrome gagal diluncurkan. |
200
+
201
+ ---
202
+
203
+ ## Pengujian & Pengembangan
204
+
205
+ Menjalankan seluruh rangkaian tes unit offline (stdlib, tanpa memerlukan login atau koneksi eksternal):
206
+
207
+ ```sh
208
+ python3 -m unittest discover -s tests -v
209
+ ```
210
+
211
+ Uji sanitasi paket wheel dan instalasi lingkungan terisolasi:
212
+
213
+ ```sh
214
+ pip install -e '.[dev]'
215
+ uv build
216
+ TOOLOST_TEST_DIST_DIR=dist python3 -m unittest tests/test_packaging.py -v
217
+ ```
218
+
219
+ Pemeriksaan gaya kode dan whitespace git:
220
+
221
+ ```sh
222
+ git diff --check
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Dokumentasi Arsitektur & Riset
228
+
229
+ - [Rencana Integrasi ke yt-to-flowmusic](docs/INTEGRATION-PLAN.md) — Arsitektur adapter subprocess async & Textual UI.
230
+ - [Rencana Packaging & Distribusi PyPI](docs/PACKAGING-PLAN.md) — Roadmap dan checklist packaging.
231
+ - [Antrean Pekerjaan Utama & Backlog](docs/ANTRIAN-PEKERJAAN-UTAMA.md) — Pelacakan status task engineering, klaim, dan acceptance.
232
+ - [Riwayat Checkpoint Rekayasa](docs/backlog/CHECKPOINT-HISTORY.md) — Bukti eksekusi dan log verifikasi.
233
+ - [Review CLI & Analisis Kontrak](docs/CLI-REVIEW.md) — Pemetaan fitur yang diimplementasikan vs proposed.
234
+
235
+ ---
236
+
237
+ ## Kebijakan Keamanan & Privasi
238
+
239
+ 1. **Penyimpanan Sesi Lokal**: Folder `.local/` berisi session cookie Chrome privat dan attempt journal tidak pernah di-commit atau dimasukkan ke dalam paket distribusi sdist/wheel.
240
+ 2. **Tanpa Otomasi Kredensial**: Tool ini tidak membaca password operator, tidak melakukan scraping cookie secara ilegal, dan tidak mencoba melewati CAPTCHA/2FA.
241
+ 3. **Draft Only**: Operasi rilis dihentikan di level penyimpanan draft untuk ditinjau oleh operator manusia sebelum proses rilis aktual.
242
+
243
+ ---
244
+
245
+ ## Lisensi
246
+
247
+ Proyek ini didistribusikan di bawah lisensi [MIT License](LICENSE).
248
+ Hak Cipta (c) 2026 Gunamaya / KiriminAja.
@@ -0,0 +1,221 @@
1
+ # Toolost Uploader
2
+
3
+ CLI & Playwright Automation Tool untuk manajemen dan upload draft rilis [Too Lost](https://toolost.com) berbasis manifest JSON.
4
+
5
+ [![PyPI version](https://img.shields.io/badge/version-0.1.0-blue.svg)](https://pypi.org/project/toolost-uploader/)
6
+ [![Python versions](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://www.python.org/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
+ [![Tests](https://img.shields.io/badge/tests-171%20passed-brightgreen.svg)](#pengujian--pengembangan)
9
+
10
+ ---
11
+
12
+ ## Fitur Utama
13
+
14
+ - **Validasi Manifest Offline**: Memvalidasi metadata rilis (Single & Album), resolusi artwork (3000×3000px), format audio (MP3/WAV/FLAC), dan kecocokan hash integritas berkas (SHA-256) tanpa membuka jaringan atau browser.
15
+ - **Sesi Browser Mandiri & Aman**: Membuka Google Chrome biasa di profil lokal terisolasi (`.local/profiles/<alias>`) agar operator dapat login manual dengan aman tanpa menyimpan password/cookie mentah di kode repo.
16
+ - **Auto-Bootup & Readiness Check**: Diagnosa otomatis ketersediaan binary Chrome, status lock profil, port CDP (Chrome DevTools Protocol loopback), dan verifikasi sesi login aktif Too Lost terhadap `--expected-account`.
17
+ - **Eksekutor Playwright Single & Multi-Track Album**: Mengotomatisasi pemilihan tipe rilis, pengisian judul, upload & encoding artwork, multi-track audio, penataan urutan track, pengisian metadata AI per-track, hingga eksekusi simpan perubahan (*Save Changes*).
18
+ - **Safety First (Draft-Only Guard)**: Eksekusi dibatasi secara ketat hanya sampai penyimpanan draft (`--draft-only`). Tool ini **tidak pernah** menekan tombol Publish atau memicu distribusi rilis.
19
+ - **Desain Integrasi Subprocess**: Format keluaran stdout JSON murni yang deterministik dan aliran log progres real-time ke stderr, sangat ramah untuk integrasi aplikasi induk seperti [yt-to-flowmusic](docs/INTEGRATION-PLAN.md).
20
+
21
+ ---
22
+
23
+ ## Instalasi
24
+
25
+ ### Dari PyPI (Rekomendasi)
26
+
27
+ ```sh
28
+ pip install toolost-uploader
29
+ playwright install chromium
30
+ ```
31
+
32
+ ### Dari Source / Git
33
+
34
+ ```sh
35
+ git clone https://github.com/gunamaya/toolost-uploader.git
36
+ cd toolost-uploader
37
+ python3 -m venv .venv
38
+ source .venv/bin/activate
39
+ pip install -e .
40
+ playwright install chromium
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Panduan Penggunaan Cepat
46
+
47
+ Alur kerja umum terdiri dari 4 langkah berurutan:
48
+
49
+ ```mermaid
50
+ flowchart LR
51
+ A["1. Validasi Manifest<br/>(toolost validate)"] --> B["2. Setup Browser Login<br/>(toolost setup)"]
52
+ B --> C["3. Cek Kesiapan<br/>(toolost check)"]
53
+ C --> D["4. Upload Simpan Draft<br/>(toolost upload --draft-only)"]
54
+ ```
55
+
56
+ ### 1. Validasi Manifest Rilis (Offline)
57
+
58
+ Periksa integritas manifest JSON dan kecocokan hash SHA-256 berkas lokal:
59
+
60
+ ```sh
61
+ toolost validate path/to/manifest.json --json
62
+ ```
63
+
64
+ ### 2. Setup Sesi Browser (Login Manual Operator)
65
+
66
+ Buka browser Chrome lokal untuk login manual ke portal Too Lost. Sesi login akan disimpan secara privat di folder profil lokal:
67
+
68
+ ```sh
69
+ toolost setup --profile production
70
+ ```
71
+ *Tutup jendela Chrome setelah selesai login.*
72
+
73
+ ### 3. Diagnosa Kesiapan Lingkungan (Readiness Check)
74
+
75
+ Pastikan Google Chrome, port CDP, dan sesi akun siap:
76
+
77
+ ```sh
78
+ toolost check --profile production --expected-account 422512 --auto-bootup --json
79
+ ```
80
+
81
+ Contoh keluaran JSON (`exit code 0`):
82
+ ```json
83
+ {
84
+ "status": "ready",
85
+ "chrome_binary": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
86
+ "profile_dir": "/path/to/.local/profiles/production",
87
+ "cdp_url": "http://127.0.0.1:9437",
88
+ "auth": {
89
+ "status": "authenticated",
90
+ "account_id": "422512"
91
+ }
92
+ }
93
+ ```
94
+
95
+ ### 4. Unggah & Simpan Draft Rilis
96
+
97
+ Jalankan otomatisasi upload Playwright. Port CDP akan otomatis di-bootup bila belum aktif:
98
+
99
+ ```sh
100
+ toolost upload path/to/manifest.json \
101
+ --draft-only \
102
+ --profile production \
103
+ --expected-account 422512 \
104
+ --approve-draft \
105
+ --accept-ui-date \
106
+ --verbose \
107
+ --json
108
+ ```
109
+
110
+ Contoh keluaran JSON sukses:
111
+ ```json
112
+ {
113
+ "status": "draft_saved_subset",
114
+ "run_id": "20261026-154000-album-test",
115
+ "draft_id": "2004317",
116
+ "warnings": [
117
+ "Tanggal UI diwarisi; bukan release_date manifest terverifikasi.",
118
+ "Remote track identity dan rights/services belum diverifikasi; bukan siap distribusi."
119
+ ]
120
+ }
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Spesifikasi Manifest JSON (Schema v1)
126
+
127
+ Contoh manifest untuk rilis Album multi-track:
128
+
129
+ ```json
130
+ {
131
+ "schema_version": 1,
132
+ "release_id": "album-project-001",
133
+ "release_type": "album",
134
+ "title": "Album Eksperimental FlowMusic",
135
+ "release_date": "2026-11-01",
136
+ "artwork": {
137
+ "path": "/path/to/artwork-3000x3000.png",
138
+ "sha256": "338ca5ab7fb090dfa5b6cdc8fd6c68f2f8afa939266e412d85ee35187b275de6"
139
+ },
140
+ "tracks": [
141
+ {
142
+ "track_id": "track-01",
143
+ "title": "Terangnya Belum Pulang",
144
+ "audio": {
145
+ "path": "/path/to/track-01.mp3",
146
+ "sha256": "53431441811b965acc69664ec4e2dcf47d5765c2ddc483f4daf49ded30a7214d"
147
+ },
148
+ "ai_assisted": true
149
+ },
150
+ {
151
+ "track_id": "track-02",
152
+ "title": "Sungai Teh Susu",
153
+ "audio": {
154
+ "path": "/path/to/track-02.mp3",
155
+ "sha256": "4278102d0dcc1ba4e1886ba518552c1a974a8f88679536a021b3896eaecf61f1"
156
+ },
157
+ "ai_assisted": true
158
+ }
159
+ ]
160
+ }
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Referensi Kode Keluar (Exit Codes)
166
+
167
+ | Exit Code | Status JSON | Makna & Tindakan Penanganan |
168
+ |---|---|---|
169
+ | **`0`** | `valid`, `ready`, `draft_saved_subset` | Eksekusi sukses. Payload JSON memuat informasi rilis / kesiapan. |
170
+ | **`2`** | `invalid_input`, `login_required`, `account_mismatch` | Argumen salah, hash aset tidak cocok, atau sesi login perlu diperbarui melalui `toolost setup`. |
171
+ | **`4`** | `reconciliation_required` | Operasi dihentikan aman (*fail-stop*). Periksa status browser atau koneksi. Hindari melakukan *retry* buta. |
172
+ | **`5`** | Error I/O / OS | File tidak ditemukan atau binary Chrome gagal diluncurkan. |
173
+
174
+ ---
175
+
176
+ ## Pengujian & Pengembangan
177
+
178
+ Menjalankan seluruh rangkaian tes unit offline (stdlib, tanpa memerlukan login atau koneksi eksternal):
179
+
180
+ ```sh
181
+ python3 -m unittest discover -s tests -v
182
+ ```
183
+
184
+ Uji sanitasi paket wheel dan instalasi lingkungan terisolasi:
185
+
186
+ ```sh
187
+ pip install -e '.[dev]'
188
+ uv build
189
+ TOOLOST_TEST_DIST_DIR=dist python3 -m unittest tests/test_packaging.py -v
190
+ ```
191
+
192
+ Pemeriksaan gaya kode dan whitespace git:
193
+
194
+ ```sh
195
+ git diff --check
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Dokumentasi Arsitektur & Riset
201
+
202
+ - [Rencana Integrasi ke yt-to-flowmusic](docs/INTEGRATION-PLAN.md) — Arsitektur adapter subprocess async & Textual UI.
203
+ - [Rencana Packaging & Distribusi PyPI](docs/PACKAGING-PLAN.md) — Roadmap dan checklist packaging.
204
+ - [Antrean Pekerjaan Utama & Backlog](docs/ANTRIAN-PEKERJAAN-UTAMA.md) — Pelacakan status task engineering, klaim, dan acceptance.
205
+ - [Riwayat Checkpoint Rekayasa](docs/backlog/CHECKPOINT-HISTORY.md) — Bukti eksekusi dan log verifikasi.
206
+ - [Review CLI & Analisis Kontrak](docs/CLI-REVIEW.md) — Pemetaan fitur yang diimplementasikan vs proposed.
207
+
208
+ ---
209
+
210
+ ## Kebijakan Keamanan & Privasi
211
+
212
+ 1. **Penyimpanan Sesi Lokal**: Folder `.local/` berisi session cookie Chrome privat dan attempt journal tidak pernah di-commit atau dimasukkan ke dalam paket distribusi sdist/wheel.
213
+ 2. **Tanpa Otomasi Kredensial**: Tool ini tidak membaca password operator, tidak melakukan scraping cookie secara ilegal, dan tidak mencoba melewati CAPTCHA/2FA.
214
+ 3. **Draft Only**: Operasi rilis dihentikan di level penyimpanan draft untuk ditinjau oleh operator manusia sebelum proses rilis aktual.
215
+
216
+ ---
217
+
218
+ ## Lisensi
219
+
220
+ Proyek ini didistribusikan di bawah lisensi [MIT License](LICENSE).
221
+ Hak Cipta (c) 2026 Gunamaya / KiriminAja.
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Toolost offline manifest v1 (unreleased)",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": ["schema_version", "release_id", "release_type", "title", "release_date", "artwork", "tracks"],
7
+ "properties": {
8
+ "schema_version": {"type": "integer", "const": 1},
9
+ "release_id": {"$ref": "#/$defs/id"},
10
+ "release_type": {"enum": ["album", "ep", "single", "compilation"]},
11
+ "title": {"$ref": "#/$defs/text"},
12
+ "release_date": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$", "format": "date"},
13
+ "artwork": {"$ref": "#/$defs/file"},
14
+ "language": {"$ref": "#/$defs/text"},
15
+ "primary_genre": {"$ref": "#/$defs/text"},
16
+ "secondary_genre": {"$ref": "#/$defs/text"},
17
+ "label": {"$ref": "#/$defs/text"},
18
+ "upc": {"$ref": "#/$defs/text"},
19
+ "copyright": {
20
+ "type": "object", "additionalProperties": false, "minProperties": 1,
21
+ "properties": {
22
+ "c_year": {"type": "integer", "minimum": 1, "maximum": 9999},
23
+ "p_year": {"type": "integer", "minimum": 1, "maximum": 9999},
24
+ "c_owner": {"$ref": "#/$defs/text"},
25
+ "p_owner": {"$ref": "#/$defs/text"}
26
+ }
27
+ },
28
+ "tracks": {
29
+ "type": "array", "minItems": 1, "maxItems": 1000,
30
+ "items": {
31
+ "type": "object", "additionalProperties": false,
32
+ "required": ["track_id", "title", "audio", "ai_assisted"],
33
+ "properties": {
34
+ "track_id": {"$ref": "#/$defs/id"},
35
+ "title": {"$ref": "#/$defs/text"},
36
+ "audio": {"$ref": "#/$defs/file"},
37
+ "lyrics": {"$ref": "#/$defs/file"},
38
+ "ai_assisted": {"type": "boolean"},
39
+ "provenance_known_ai_generated": {"type": "boolean"},
40
+ "version_line": {"$ref": "#/$defs/text"},
41
+ "language": {"$ref": "#/$defs/text"},
42
+ "instrumental": {"type": "boolean"},
43
+ "explicit": {"type": "boolean"},
44
+ "clean_version": {"type": "boolean"},
45
+ "isrc": {"$ref": "#/$defs/text"},
46
+ "iswc": {"$ref": "#/$defs/text"}
47
+ }
48
+ }
49
+ }
50
+ },
51
+ "$defs": {
52
+ "text": {"type": "string", "pattern": "\\S"},
53
+ "id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,128}$"},
54
+ "file": {
55
+ "type": "object", "additionalProperties": false, "required": ["path", "sha256"],
56
+ "properties": {
57
+ "path": {"type": "string", "pattern": "\\S"},
58
+ "sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}
59
+ }
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "Toolost offline validate result v1 (unreleased)",
4
+ "type": "object", "additionalProperties": false,
5
+ "required": ["schema_version", "command", "run_id", "status", "profile", "release_id", "draft_id", "remote_verified", "issues", "warnings", "error"],
6
+ "properties": {
7
+ "schema_version": {"type": "integer", "const": 1},
8
+ "command": {"const": "validate"},
9
+ "run_id": {"type": "null"},
10
+ "status": {"enum": ["valid", "invalid_input"]},
11
+ "profile": {"type": "null"},
12
+ "release_id": {"type": ["string", "null"], "pattern": "^[A-Za-z0-9_-]{1,128}$"},
13
+ "draft_id": {"type": "null"},
14
+ "remote_verified": {"const": false},
15
+ "issues": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["code", "scope", "message"], "properties": {"code": {"type": "string"}, "scope": {"type": "string"}, "message": {"type": "string"}}}},
16
+ "warnings": {"type": "array", "items": {"type": "string"}},
17
+ "error": {"type": ["object", "null"], "additionalProperties": false, "required": ["code", "message", "retryable"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}, "retryable": {"const": false}}}
18
+ },
19
+ "allOf": [
20
+ {"if": {"properties": {"status": {"const": "valid"}}}, "then": {"properties": {"release_id": {"type": "string"}, "issues": {"maxItems": 0}, "error": {"type": "null"}}}},
21
+ {"if": {"properties": {"status": {"const": "invalid_input"}}}, "then": {"properties": {"issues": {"minItems": 1}, "error": {"type": "object"}}}}
22
+ ]
23
+ }
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.3"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "toolost-uploader"
7
+ dynamic = ["version"]
8
+ description = "CLI and Playwright automation tool for Too Lost music release manifests"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Gunamaya", email = "developer@kiriminaja.com" }
14
+ ]
15
+ keywords = ["too-lost", "music-distribution", "uploader", "playwright", "automation"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Topic :: Multimedia :: Sound/Audio",
24
+ ]
25
+ dependencies = [
26
+ "playwright>=1.40.0,<2",
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ dev = ["build>=1.2.2,<2", "twine>=5.0.0,<6", "jsonschema>=4.26,<5"]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/gunamaya/toolost-uploader"
34
+ Repository = "https://github.com/gunamaya/toolost-uploader"
35
+ Issues = "https://github.com/gunamaya/toolost-uploader/issues"
36
+
37
+ [project.scripts]
38
+ toolost = "toolost_uploader.cli:main"
39
+
40
+ [tool.setuptools]
41
+ packages = ["toolost_uploader"]
42
+ include-package-data = false
43
+
44
+ [tool.setuptools.dynamic]
45
+ version = {attr = "toolost_uploader.__version__"}
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+