Skip to content
Merged
44 changes: 44 additions & 0 deletions docs/decisions/0015-manual-html-not-pdf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# 0015: 解説マニュアル(生成した HTML)は PDF にせず、HTML のまま配信する

- 状態:見送り
- 決めた日:2026-05-31(PM の作業メモ)
- 決めた人:45th の PM
- 決定の信頼度:記録なし
- 根拠:出典の PM の作業メモ(2026-05-31 の検討)を読んだ。決めたことと、見直す条件(印刷用に中身を固定した版が要るとき)は書かれているが、どれだけ確かだと思っていたかは書かれていない
- 出典:45th の PM の作業メモ(公開していない)

## 背景

45th では、各局のマニュアル(Google ドキュメント)を、AI でスマホ向けの HTML に変換して配った(解説マニュアル)。HTML には画像を埋め込み、1ファイルで開けるようにしてある。

2026-05-31 に、この HTML を配るときに PDF にするかを検討した。

## 候補

| 候補 | 良い点 | 悪い点 |
| --- | --- | --- |
| 軽い変換ツール(Chromium を使わないもの)で PDF にする | 速い。PM の作業メモでは、実物の HTML 2本を変換して、4.6MB の HTML が 3.7 秒で 7.9MB の PDF になった | 目次のページ内リンクや電話番号のリンクが PDF に残らなかった(PM の作業メモ) |
| Chromium を使うツールで PDF にする | リンクは残せる | 軽さが無くなる。HTML の動く部分は、どのツールでも失われる |
| PDF にせず、HTML のまま配る | HTML の動く部分がそのまま使える | 印刷や、中身を固定した版が欲しいときには向かない |

## 決定

解説マニュアルは PDF にせず、HTML のまま配る。

印刷用に中身を固定した版と、章へ飛ぶリンクだけが欲しい、という要望が出たときに限り、Chromium を使うツールでの PDF 化を考え直す。

## 理由

解説マニュアルの HTML には、PDF では動かない部分がある。画像を拡大表示する機能、画面の端に出る目次のボタン、章ごとの折りたたみである。PDF にすると、これらがすべて使えなくなる。

## 前提

- HTML の動く部分は、生成に使うプロンプトで指定している:`.claude/manual-prompt-card-strict.md`(画像の拡大は `openLightbox`、目次のボタンは `toggleTocOverlay`、章の折りたたみは `<details>`)
- 配信は `api/lib/internals/controller/manual_controller.go#manualController.ShowManual`([0006](0006-manual-serving-google-gate.md))
- 簡易マニュアル(Google ドキュメントやスライドをそのまま使うもの)を PDF にするのは、この判断と別の話である。元が動かない文書なので、PDF にしても失うものが無い([0016](0016-simple-manual-pdf-on-drive.md))

## 結果

45th の技大祭は、解説マニュアルを HTML のまま配った。

## 追記
51 changes: 51 additions & 0 deletions docs/decisions/0016-simple-manual-pdf-on-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# 0016: 簡易マニュアルは PDF にして Drive に置き、アプリからそこへ移動させる

- 状態:採用
- 決めた日:2026-08-23(アプリへの埋め込みを検証した日。PM の作業メモ)。対象を広げたのは 2026-09-12(#248 を閉じた日)
- 決めた人:45th の PM
- 決定の信頼度:記録なし
- 根拠:#248・PR #521 には、決めたことと置き方は書かれているが、どれだけ確かだと思っていたかは書かれていない
- 出典:#248、PR #521

## 背景

45th のマニュアルのうち、AI で HTML に変換しないもの(簡易マニュアル)は、各局が作った Google ドキュメントやスライドのままだった。スマホで Google ドキュメントを直接開くと、表や図の配置が崩れて読みにくかった。

マニュアルには、部門長や局長の電話番号と名前が書いてあるものがあり、技大祭の関係者だけが読めるようにしたかった(PM の作業メモ)。

## 候補

| 候補 | 良い点 | 悪い点 |
| --- | --- | --- |
| アプリの中に埋め込んで表示する(#248) | アプリから出ずに読める | Google のログイン画面が、別のサイトの中への埋め込みを拒む。別のサイトの Cookie も遮られる。そのため、読める人を nutfes の Google アカウントに絞ることと両立しない(2026-08-23 に確かめた) |
| PDF にして SeeFT のサーバーに置く | 置くのが簡単 | 8/23 の時点では、SeeFT のサーバーに、読める人を絞って配る仕組みがまだ無かった(ログインで絞る仕組みが入ったのは 8/25。[0006](0006-manual-serving-google-gate.md)) |
| PDF にして技大祭の Drive のフォルダに置き、アプリからそこへ移動させる | 崩れずに読める。フォルダの共有の設定で、読める人を nutfes の Google アカウントに絞れる | アプリから Drive に移動する |

## 決定

簡易マニュアルは、元のドキュメントを PDF にして、技大祭の Drive のフォルダに置く。アプリのボタンからは、その PDF に移動する。読める人は、フォルダの共有の設定で絞る。

2026-09-12 に、対象を広げた。マニュアルの割り当て表にあるものは、タスクに紐づくかどうかに関係なく、すべて Drive に置き、マニュアル一覧からたどれるようにする。アプリの中で PDF を表示する issue(#248)は、この日に「予定しない」として閉じた。

置き方は、マニュアルの割り当て表に付いた GAS で行う(PR #521)。

- ファイル名は、割り当て表の「マニュアル名」を使う。元のドキュメントのタイトルは、局ごとに付け方がばらばらだった
- スプレッドシートや、もともと PDF のものは、コピーせずにショートカットを置く。コピーすると、元を直しても反映されない
- 出し直すときは、同じファイル ID のまま中身だけを差し替える。ファイルが変わると URL が変わり、対応表・DB・アプリのボタンの3か所を直す必要がある
- 置き先の局のフォルダに同じ名前のファイルがすでにあれば、その行はエラーにして置かない

## 理由

崩れずに読めることと、読める人を絞ることを、両方満たせたのが Drive に置く案だけだった。埋め込みはログインと両立せず、SeeFT のサーバーには、当時は読める人を絞って配る仕組みが無かった。

## 前提

- 置き方の GAS:`gas/manual-assignment/PDF配置.js#place_`、出し直しは `gas/manual-assignment/PDF配置.js#refreshPdfs`、同じ名前の確認は `gas/manual-assignment/PDF配置.js#flagExistingNames_`、ショートカットにする種類は `gas/manual-assignment/PDF配置.js#PLACE_SHORTCUT`、対象にする状態は `gas/manual-assignment/PDF配置.js#TARGET_STATUSES`
- nutfes の Google アカウントは全員 @gmail.com で、Google Workspace の共有ドライブは無い。フォルダは、技大祭で使っている Google アカウントのマイドライブを共有したものである
- 解説マニュアル(生成した HTML)は PDF にしない([0015](0015-manual-html-not-pdf.md))。簡易マニュアルは元が動かない文書なので、PDF にしても失うものが無い

## 結果

45th の技大祭では、簡易マニュアルをこの形で配った。

## 追記
49 changes: 49 additions & 0 deletions docs/decisions/0017-manual-ops-not-automated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 0017: マニュアル運用のスプレッドシートの操作は自動化しない

- 状態:見送り
- 決めた日:2026-06-18(状態の監視。手順書 `docs/proposals/manual-slide-operations.md` を足したコミット 0f4c921 の日付)、2026-08-31(対応表への記入。PR #487 をマージした日)
- 決めた人:45th の PM
- 決定の信頼度:記録なし
- 根拠:`docs/proposals/manual-slide-operations.md`・`docs/proposals/manual-proposal-v4-slides/automation-design.md`・#486・PR #487 には、決めたことと理由、見直す条件(状態の管理を自動化したくなったとき)は書かれているが、どれだけ確かだと思っていたかは書かれていない
- 出典:`docs/proposals/manual-slide-operations.md`、`docs/proposals/manual-proposal-v4-slides/automation-design.md`、#486、PR #487

## 背景

解説マニュアルを作って配るまでには、生成・確認・部門長のチェック・アップロード・タスクへの紐付けと、いくつもの手作業がある。

2026 年 5 月に、この流れをスプレッドシートで管理する自動化を設計し、コードも書いた。スプレッドシートの行を常に監視し、状態が変わったら次の作業を進める仕組みである(`scripts/automation/` の watcher・sheets_client・drive_client)。

8 月には、手順を文書にして誰でも作業できるようにしたが、マニュアル1本を配るのに手作業が 10 手かかるのは変わっていなかった(#486)。

## 候補

| 候補 | 良い点 | 悪い点 |
| --- | --- | --- |
| スプレッドシートを軸に、状態の監視から対応表への記入まで自動化する | 手作業が減る | 部門長にスプレッドシートを開いてもらう必要がある。常に監視する仕組みは重い。Google の API を使うための設定(GCP のプロジェクトと認証情報)が、作業する人ごとに要る |
| 状態の管理は Slack のスレッドで行い、手作業を減らせるところだけコマンドにする | 部門長は Slack だけ見ればよい。新しく入った人も、設定なしで作業を始められる | 対応表への記入とタスクの送信は、手作業のまま残る |

## 決定

マニュアル運用のスプレッドシートの操作は、自動化しない。

- 2026-06-18:本番は、Slack のスレッドを中心にした手作業の流れで運用する。状態の監視の自動化は、コードを残したまま保留にする(`docs/proposals/manual-slide-operations.md`)
- 2026-08-31:手作業を 10 手から 7 手に減らした(PR #487)。残る7手のうち、対応表への記入とタスクの送信の2手は自動化しない

## 理由

状態の監視を保留にしたのは、部門長にスプレッドシートを開かせずに済ませたかったからである。状態の管理は SeeFT の仕事にして、部門長は Slack のスレッドだけを見れば済む形にした。常に監視する仕組みは、ほぼ1人の運用には重すぎた。

対応表への記入を自動化しなかったのは、Google の API を使うと、作業する人ごとに GCP のプロジェクトや認証情報の設定が要るからである。PR #487 では、「新しく入った人が最初の1本を出すまでの時間」で比べると、自動化すると逆に遅くなると判断した。

## 前提

- 保留にした自動化のコード:`scripts/automation/watcher.py`、`scripts/automation/sheets_client.py`、`scripts/automation/drive_client.py`。今の運用では使っていない
- 設計:`docs/proposals/manual-proposal-v4-slides/automation-design.md`
- 今の運用の手順:`docs/proposals/manual-slide-operations.md`、`docs/development/manual-html-operations.md`
- ほぼ1人で運用していること。担当する人が増えて、状態の管理が Slack で追いきれなくなったら、自動化を考え直す

## 結果

45th は、Slack のスレッドを中心にした手作業の流れで、マニュアルを配った。

## 追記
42 changes: 42 additions & 0 deletions docs/decisions/0018-test-mock-with-sqlmock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 0018: テストでは db.Client に go-sqlmock の偽の DB を差し込み、repository の戻り値は変えない

- 状態:採用
- 決めた日:2026-07-07(PR #392 をマージした日)
- 決めた人:45th の PM
- 決定の信頼度:記録なし
- 根拠:#391・PR #392・`docs/development/test-roadmap.md` には、決めたことと、案 B を選ばなかった理由は書かれているが、どれだけ確かだと思っていたかは書かれていない
- 出典:#391、PR #392、`docs/development/test-roadmap.md`(「前提: コード構造がテスト戦略を規定する」)

## 背景

2026-07-06 の MT で、SeeFT 本体は保守性を上げる方向に決まり、直す前にテストを書くことになった([0003](0003-maintenance-over-features.md))。
Comment thread
coderabbitai[bot] marked this conversation as resolved.

api の repository は、ほとんどが `database/sql` の `*sql.Rows` や `*sql.Row` を返し、値の読み取り(Scan)は usecase の側で行う作りになっている。`*sql.Row` はテストのコードから作れない。そのため、repository のインターフェースを偽物に差し替えても、usecase のテストが書けなかった。

## 候補

| 候補 | 良い点 | 悪い点 |
| --- | --- | --- |
| A:DB への接続(`db.Client`)に、go-sqlmock の偽の `*sql.DB` を差し込む | 今のコードを直さなくてよい。repository の実装ごとテストできる | テストに SQL の文字列を書く必要がある |
| B:repository の戻り値を entity に変える | テストが書きやすくなる | 141 のメソッドに手を入れる大きな作業になる |

## 決定

案 A をとる。テストでは、`db.Client` に go-sqlmock の偽の `*sql.DB` を差し込む。repository の戻り値は変えない。

## 理由

案 B は、141 のメソッドに手を入れる大きな作業で、保守に寄せる方針([0003](0003-maintenance-over-features.md))で手を付けられる大きさを超えていた。案 A なら、今のコードを変えずにテストを書き始められる。

## 前提

- 差し込む先のインターフェース:`api/lib/externals/db/db.go#Client`
- テストで使う偽物:`api/lib/internals/repository/sqlmock_helper_test.go#fakeDBClient`
- テストの進め方:`docs/development/test-roadmap.md`
- repository が `*sql.Rows` や `*sql.Row` を返す作りであること。戻り値を entity に変える作業をするなら、この ADR を見直す

## 結果

2026-09-30 の時点で、`api/` のテストのファイルは 18 本ある。そのうち 9 本が go-sqlmock を使うテストで(ファイル名が `_sqlmock_test.go` のもの。repository と usecase の両方)、ほかに偽物を作る補助のファイルが1本ある。

## 追記
4 changes: 4 additions & 0 deletions docs/decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,7 @@ python3 scripts/refcheck/refcheck.py docs/decisions/*.md
| [0012](0012-slack-id-linked-by-gas.md) | Slack ID の紐付けは GAS の名簿送信で行い、API に一括のバッチは作らない | 採用 |
| [0013](0013-rescue-dm-sent-immediately.md) | レスキューの対応状況の DM は、まとめずに、書き換えのたびにすぐ送る | 採用 |
| [0014](0014-manual-open-in-new-tab.md) | マニュアルはアプリに埋め込まず、別タブで開く | 採用 |
| [0015](0015-manual-html-not-pdf.md) | 解説マニュアル(生成した HTML)は PDF にせず、HTML のまま配信する | 見送り |
| [0016](0016-simple-manual-pdf-on-drive.md) | 簡易マニュアルは PDF にして Drive に置き、アプリからそこへ移動させる | 採用 |
| [0017](0017-manual-ops-not-automated.md) | マニュアル運用のスプレッドシートの操作は自動化しない | 見送り |
| [0018](0018-test-mock-with-sqlmock.md) | テストでは db.Client に go-sqlmock の偽の DB を差し込み、repository の戻り値は変えない | 採用 |
Loading