# NAIメタデータビューアー 生成手順 (他の MUSE 向け)

`nai.py` で生成した NovelAI 画像のメタデータを、原本のまま保管して見やすく確認するための
スペース「NAIメタデータビューアー」の作り方。生成システム本体の使い方は `README.md` を参照。

## なぜこのスペースが要るのか

- チャットに貼った画像はメタデータが剥がれる (表示用に再圧縮されるため)。
- `out/` の原本 PNG にはメタデータが完全な形で残っているので、原本ごと保管して
  チャンク解析だけで表示する受け口が要る。
- 最初に作った静的 (ブラウザ内だけ) 版は保存ができなかったため、**サーバー保存型が正**。
  作り直す場合も必ずサーバー保存型にすること。

## 対象物

| 項目 | 内容 |
|---|---|
| 名前 | NAIメタデータビューアー |
| スラッグ | `naimetadetabiyua-2` |
| 種類 | サーバー保存型の Web スペース (`web_fullstack`)、サイドバーに置く |
| 同期元 | `~/workspace/nai-wildcard/out/` (nai.py の出力フォルダ) |

**既にこのスラッグのスペースが存在する場合は、新規作成せず `artifact.edit` で改修すること。**
二重に作ると保管データが分裂する。

## 生成手順

1. 前提を確認する: `~/workspace/nai-wildcard/` に `nai.py` と `out/` があること。
   同期元が無いスペースは意味がない。
2. `artifact.create_web_fullstack` で作成する。
   - `name`: 「NAIメタデータビューアー」
   - `place_in_sidebar`: true
   - `refresh_triggers`: 15分ごとの同期 (下記「同期仕様」の `syncgeneratedimages` を回す)
   - `verbatim_request` には下記「機能仕様」を過不足なく要件として渡す
3. 初回同期で `out/` の既存 PNG と実行ログ JSON が取り込まれることを確認する。
4. 下記「検証チェックリスト」を全部通してから完了とする。

## 機能仕様 (ビルダーへ渡す要件)

### 保管と同期

- 同期アクション `syncgeneratedimages`: `out/` にあってスペースがまだ持っていない PNG と
  実行ログ JSON を全部取り込む。**バイト単位で原本のまま**転送し、画像の中身は開かない・見ない。
  解析は PNG チャンク (テキストチャンク) の読み取りだけ。
- 同期は冪等: ファイル名で重複判定し、2回目以降は新しい分だけ入る。
- 15分ごとの自動同期 + ページ内の「生成フォルダと同期」ボタンで即時同期。
- 実行ログは、それが生成した画像とリンクする (ファイル名・シードで対応付け)。

### 公開アクション

| アクション | 役割 |
|---|---|
| `listimages` | 保管中の全 PNG を新しい順に一覧 (メタデータ要約 + リンク済み実行ログ) |
| `getimage` | 1枚の完全な解析結果 (プロンプト/ネガティブ/パラメータ/V4キャラプロンプト/全テキストチャンク/生 Comment JSON) + リンク済み実行ログ |
| `importimage` | PNG を base64 で受けて原本のまま保管し、メタデータを解析して登録 (手動ドロップ用。重複ファイル名はスキップ) |
| `importrunlog` | 実行ログ JSON を取り込み、生成画像とリンク (重複はスキップ) |
| `syncgeneratedimages` | 上記の自動/手動同期 |
| `deleteimage` / `deleterunlog` | 保管中の PNG / 実行ログを1件削除。生成由来の PNG は `out/` の元ファイルも一緒に削除する |
| `deleteimages` | PNG を複数件まとめて実削除 (保管バイト+メタデータ行)。入力は `{ ids: number[] }` (1件以上、最大500件)。生成由来のものは `out/` の元ファイルも削除し、同期で復活させない。戻り値は `{ ok, deleted, sourceFilesDeleted }` |

### 削除仕様 (実データ削除)

- 削除は「一覧から隠す」ではなく**実削除**にする。スペースが保管している PNG バイトと
  メタデータ行を消し、生成由来の画像については同期元 `out/` の元 PNG ファイルも消す。
  DB レコードだけ消すと、次の自動同期 (15分ごと) で `out/` から再取り込みされて復活するので不可。
- 画像レコードには少なくとも `id` / `filename` / `source` (生成由来か手動取り込みか) /
  保管バイトへの参照 / リンク済み実行ログのファイル名を持たせる。`out/` の実ファイル削除は
  **`source` が生成由来のレコードだけ**に行い、手動取り込み画像では利用者の元ファイルに触れない。
- 実ファイル削除はサーバー側の専用経路で行う。ファイル名は必ず検証する: ベース名のみ、
  `.png` で終わること、パス区切りや `..` を含まないこと、解決後のパスが
  `~/workspace/nai-wildcard/out/` の中にあること。検証を通らない名前は削除対象にしない。
- `deleteimages` の処理: ID 群から対象レコードを集め、生成由来のものは元ファイルを削除して
  `sourceFilesDeleted` に数え、保管バイトとメタデータ行を削除して `deleted` に数える。
  元ファイル削除に失敗した件を成功として黙って扱わないこと (結果や画面表示で切り分ける)。
- 詳細画面の単体削除 (`deleteimage`) も、まったく同じ実削除の経路を通すこと。
- 画像を消しても実行ログは自動では消さない。実行ログは独立レコードで、`deleterunlog` で消す。
  ログ側に残る生成ファイル名の参照で画面が壊れないようにすること (リンク切れとして許容する)。
- 削除は元に戻せない。検証ではプロデューサーさんの実生成 PNG を絶対に使わず、
  テスト用アップロードや `out/` に置いたダミーコピーで確認する (チェックリスト参照)。

### 解析仕様

- PNG のテキストチャンク (tEXt / zTXt / iTXt) を読む。本体は `Comment` チャンクの JSON で、
  プロンプト・ネガティブ (uc)・シード・ステップ数・スケール・サンプラー・サイズ・
  V4 キャラプロンプト (v4_prompt) が入っている。他に `Source` / `Description` /
  `Software` / `Generation_time` チャンクがある。
- サンプラー名は表示用に読み替え (例: k_euler_ancestral → Euler Ancestral)。

### 画面仕様

- ライブラリ: サムネイル一覧 (新しい順)。クリックで詳細を開く。
- 複数選択削除: 「届いた画像」見出しの「複数選択して削除」で選択モードに入り、サムネイルを
  タップして複数枚選択 (チェック表示、全て選択/選択クリア/完了あり)。選択モード中は
  サムネイルのタップで詳細を開かず選択のオン/オフだけにする。選択が0件の時は削除を実行できない。
  件数確認つきの2段階確認で `deleteimages` を実行し、実データごと削除する。確認では、
  生成由来の画像は `out/` の元ファイルも消えて元に戻せないことを明示する。
  成功後は選択モードを終えて一覧を更新し、失敗があれば画面で分かるようにする。
  詳細画面の単体削除も同じ経路。
- 詳細: プロンプトとネガティブをタグチップ表示 (クリックで個別コピー)、
  シード/ステップ数/CFG/サンプラー/サイズ等のパラメータ、
  「キャラクタープロンプト (V4)」欄 (キャラごとのキャプション・キャラ別ネガティブ・位置 x/y)、
  生 Comment JSON、チャンク一覧、メタデータの JSON 保存。
- **キャラプロンプトの補完**: PNG 側にキャラ情報が無い画像は、リンク済み実行ログの
  展開済みキャラプロンプト (位置つき) で補完表示する (出典がログであることを明示)。
- 実行ログの表示: テンプレート全文のほか、キャラテンプレート (`--char`、@x,y の位置と
  全文コピーつき) と、画像ごとの展開済みキャラプロンプトのチップ表示。
- 手動取り込み: PNG のドラッグ&ドロップ (複数可)・貼り付け・ファイル選択に対応。
  実行ログ JSON の読み込みも可。

## 検証チェックリスト

- [ ] 初回同期で `out/` の既存 PNG と実行ログが全部取り込まれる
- [ ] 再同期しても増えない (冪等)
- [ ] `getimage` でプロンプト/ネガティブ/パラメータ/全チャンク/生 JSON/リンク済みログが正しく返る
- [ ] キャラプロンプトが、PNG 由来の画像と、ログ補完の画像の両方で表示される
- [ ] 手動ドロップした PNG が原本のまま登録され、メタデータが読める
- [ ] テスト用アップロード PNG 2件を `deleteimages` で消し、`deleted=2` と一覧からの消滅を確認
      (実生成 PNG では検証しない)
- [ ] `out/` にダミーコピー PNG (実在ファイル名と衝突しない名前) を置いて同期→ `deleteimages` で消し、
      `sourceFilesDeleted=1`、`getimage` が「見つかりません」になること、再同期しても復活しないことを確認
- [ ] 監査でコンソールエラーなし、スマホ幅で横あふれなし

## 運用上の注意

- 取り込み・同期では**画像の中身を一切見ない** (バイト転送 + チャンク解析のみ)。
  これはプロデューサーさんのトークン節約ルールに合わせた仕様。
- 削除は実ファイルごと消える破壊的操作で、元に戻せない。削除 UI や削除アクションの検証は
  必ずテスト用データだけで行い、プロデューサーさんの生成物を検証に使わない。
- チャットに貼られた画像はメタデータを失うので、原本の確認は常にこのスペース (または `out/`) で行う。
- 生成そのものの運用ルール (プロンプトの決まり・受け渡し方法) は `README.md` の
  「運用ルール」に従う。このスペースはその保管・確認側だけを担当する。
