さくらコードSakura Code
小説/第5話

Novel

第5話 ひとりで読めないログ

Script

Cold Open

シーン1 二度目の自分のIssue

 六月七日。火曜日の朝。

 梅雨入り目前の、湿った曇り空だった。オフィスの窓は、結露こそしていないものの、空気のどこかが、すこし重たい。

 桜子は、自席で、社内のIssueボードを開いていた。

 今朝、桜子は、生まれて初めて、「自分で起票して、自分にアサインする」という手順を、書類のチェックボックスのように、ひとつずつ踏もうとしていた。

 タイトルを、下書きに、おそるおそる打ち込む。

共通基盤ライブラリの sakura-core が v2 に上がるので、
sakura-app 側の依存も合わせて更新する

 起票内容の本文には、社内wikiから引っ張ってきた起票テンプレートを貼り付け、空欄を、ひとつずつ、埋めていく。

### 目的
- sakura-core v2 が来週リリース予定。
  sakura-app 側を v2 対応にする
### 完了条件
- sakura-app の依存ロックファイルを更新
- pytest 緑
- v2 の breaking change への対応コードを書く
### 担当
- 望月桜子

 起票ボタンを、押す。Issue #214 が、ボードの「In Progress」列に、ぽつんと置かれた。

 (自分で、起票して、自分で、ひっぱって、自分で、進める)

 境界条件バグを出してから、ちょうど、二週間。あの日、隠したくなった一秒の感触を、桜子は、まだ覚えている。今度は、隠さない。けれど、いきなり呼ばずに、自分の手で、まず、半分まで進める。

 そう、決めていた。


Part A

シーン2 知らないエラー

 桜子は、ターミナルを開いた。

 ブランチを切り、pyproject.toml を開いて、sakura-core = "^1.4.2" の行を、sakura-core = "^2.0.0" に書き換えた。

$ poetry update sakura-core

 エンターを押すと、しばらく、ターミナルが、黙った。

 処理が、走っている。CPU ファンの音が、机の下で、低く、きん、と鳴った。

 数秒後、画面が、赤くなった。

 桜子は、息を、止めた。

Updating dependencies
Resolving dependencies...

  SolverProblemError

  Because no versions of sakura-core match >=2.0.0,<3.0.0
  and sakura-core (2.0.0) depends on sakura-utils (>=2.0.0,<3.0.0),
  sakura-core (>=2.0.0,<3.0.0) requires sakura-utils (>=2.0.0,<3.0.0).
  And because sakura-app depends on sakura-utils (^1.5.0),
  sakura-app is forbidden.
  So, because sakura-app depends on sakura-core (^2.0.0),
  version solving failed.

  at /usr/local/lib/python3.11/site-packages/poetry/.../solver.py:120 in _solve
       116│
       117│             try:
       118│                 result = self._provider.complete_package(...)
       119│             except OverrideNeeded as e:
     → 120│                 raise SolverProblemError(...)

 (読めない)

 桜子の頭の中で、最初の三秒で、降参の指が、すこし、上がりかけた。

 入社初日の環境構築のときは、もっと素直だった。Python 3.9.6 is not supported。バージョンが合わない、ということが、文字の通り、書いてあった。今日のは、違う。SolverProblemError。Because no versions of。So, version solving failed。英語と、依存パッケージ名と、バージョン範囲の記号が、絡み合っている。

 桜子は、画面のいちばん下まで、目だけで、いったんスクロールしてみた。スタックトレースは、自分のリポジトリではなく、poetry の中の solver.py で終わっていた。自分の書いたコードは、エラーの原因の地名としては、出てこない。

 (じゃあ、どこを、直せばいいの)

 ノートPCのキーボードに置いた指が、かすかに、冷たかった。


シーン3 すぐに呼びたい衝動

 Slackを開く。

 遥のアイコンが、ステータスを「集中中」にしている。けれど、新人の桜子からのDMは、たぶん、開いてくれる。入社初日のあの日、「詰まったら、呼んで。抱えないで」と言われている。

 桜子は、DM入力欄に、書きかけた。

@yamashita-haruka: 山下さん、いま、お時間ありますか。
sakura-core を v2 に上げようとして、エラーで詰まりました。

 書きながら、桜子の手は、もう一歩、画面の隅で、少し、止まった。

 境界条件バグの日の遥の声が、頭の中で、もう一度、鳴った。

 「赤いやつは、ちゃんと、桜子さんに向かって咲いてる」

 入社初日の遥の声も、続いた。

 「ログは、桜子さんに向かって書かれてる」

 桜子は、書きかけたDMを、送らずに、画面の隅へ、ちょこんと、避けた。

 Slackの未送信ドラフトは、画面の下に、薄く下線が引かれた状態で、待ってくれていた。

 (呼ぶ前に、整理しよう)

 桜子は、メモ帳を、机の真ん中に、ぽんと、置いた。


Part B

シーン4 質問テンプレート、自分のために

 メモ帳の、新人日記の隣のページを、新しく開く。

 桜子は、ページの上に、小さく、項目を立てた。

質問テンプレート (自分用)

- いま、何をしようとしているか
- 何を試したか
- どこで詰まっているか
- いまの自分の仮説
- 聞きたいこと

 ペン先を、ひとつ目の項目の右に、運ぶ。

 「いま、何をしようとしているか」。

 ……三秒、止まった。

 頭の中で、最初に出てきた答えは、「sakura-core を v2 に上げる」だった。

 でも、それは、コマンドに書いてあるレベルの、表面的な目的だった。なんで、上げるんだっけ。

 桜子は、Issue本文を、もう一度開いた。「sakura-core v2 が来週リリース予定。sakura-app 側を v2 対応にする」。

 書いてあるけれど、これも、表面だ。なぜ v2 対応するのか。たぶん、共通基盤に v2 で来る新しいAPIが、sakura-app の別タスク(鈴木が来週、桜子に渡そうとしている、未読件数のキャッシュ系のタスクのはずだ)で、使われる予定だから。

 桜子は、ペンを動かした。

- いま、何をしようとしているか
  sakura-app の依存を sakura-core v2 に追従させる。
  来週、未読件数キャッシュのタスクで v2 の新APIを使う予定があるため

 書きながら、桜子は、ほんの少しだけ、苦笑した。

 (一行で書こうとして、二行になった)

 次の項目。

- 何を試したか
  - pyproject.toml の sakura-core を ^1.4.2 から ^2.0.0 に変更
  - poetry update sakura-core を実行
  - SolverProblemError が出力された (添付予定)

 ここまでは、淡々と書ける。手を動かしているうちに、だんだんと、桜子の頭の中で、ターミナルの画面が、もう一度、整理されはじめた。

 次の項目。

- どこで詰まっているか
  エラー本文が読めない。
  特に、sakura-utils の (^1.5.0) と (>=2.0.0,<3.0.0) の対立、
  および ^ 記号の意味が、自分の中で曖昧

 書いた瞬間、桜子は、自分が「読めない」と思っていたものの正体を、初めて、外側から見た。

 (^ 記号の意味が、わかってない)

 ずっと、pyproject.toml の ^ を、なんとなく書き写していた。


シーン5 書いて、半分解ける

 桜子は、ブラウザのタブを、新しく開いた。

 検索欄に、ゆっくり、打ち込む。

poetry pyproject.toml ^ caret 意味

 最初に出てきた poetry の公式ドキュメントを、桜子は、上から、ゆっくり読んだ。^1.2.3 は、>=1.2.3, <2.0.0 を意味する。^ を「キャレット」と読む。メジャーバージョンを跨ぐと、^ の範囲外になる。

 (だから、^1.5.0 のままだと、2.0.0 に行けない)

 画面の中の、SolverProblemError の本文を、もう一度、上から下へ、ゆっくり読み直す。

sakura-core (>=2.0.0,<3.0.0) requires sakura-utils (>=2.0.0,<3.0.0).
And because sakura-app depends on sakura-utils (^1.5.0),
sakura-app is forbidden.

 「sakura-core の v2 系は、sakura-utils も v2 系を要求している」。  「でも、sakura-app は、sakura-utils を ^1.5.0 で固定してしまっている」。  「だから、両立できない」。

 今度は、文字が、ちゃんと、桜子の側に並んだ。

 ということは。

 ということは、桜子がいま、自分の判断で勝手に決められないのは、sakura-utils を、どのバージョン範囲で許すか、というチーム方針だった。sakura-utils = "^1.5.0" を、sakura-utils = "^2.0.0" に書き換えれば、たぶん、解決する。けれど、その瞬間、sakura-utils の v1 でしか動かない別の何かが、社内のどこかで壊れる可能性がある。

 桜子は、書きかけのメモ帳の、どこで詰まっているか の欄に、二重線で、追記をした。

- どこで詰まっているか (更新)
  ^ 記号の意味は理解した。
  本質の詰まりは、
  「sakura-utils を v1.5系から v2系に上げてよいか」のチーム方針が、
  自分には判断できない点

 次の項目。

- いまの自分の仮説
  pyproject.toml の sakura-utils を ^1.5.0 から ^2.0.0 に変更すれば
  依存解決は通る。
  ただし、社内で sakura-utils の v1 系API依存箇所があるなら、
  その壊れる可能性を、自分以外の人に、検証してもらう必要がある

 メモを、上から下まで、もう一度、読み返した。

 (書いたら、半分、解けた)

 桜子は、しばらく、自分の机の前で、その事実を、噛みしめた。


Part C

シーン6 残りの半分を、聞く

 桜子は、画面の隅に避けていた、未送信のSlackドラフトを、もう一度、開いた。

 最初に書きかけた文面を、選択して、まるごと、消した。

 代わりに、こう書いた。

@yamashita-haruka: 山下さん、お忙しいところすみません。
Issue #214 を進めていて、依存解決のエラーで詰まりました。
途中までメモで整理したので、貼ります。

# 質問

- 目的:
  sakura-app の依存を sakura-core v2 に追従させる
- 試したこと:
  - pyproject.toml の sakura-core を ^2.0.0 に変更
  - poetry update sakura-core で SolverProblemError
- 自分で分かったこと:
  - ^ 記号の範囲指定の意味
  - sakura-core v2 が sakura-utils v2 を要求
  - sakura-app の sakura-utils が ^1.5.0 で固定されている
- 自分の仮説:
  sakura-utils を ^2.0.0 に上げれば解決する
- 自分では決められないこと:
  sakura-utils v2 系へ社内全体で移ってよいか、
  チーム方針が分からない
- 知りたいこと:
  この方針は、誰がどう決める性質のものですか

 書き終えて、桜子は、その文面を、何度か、読み直した。

 「Issue #214」「目的」「試したこと」「自分で分かったこと」「自分の仮説」「自分では決められないこと」「知りたいこと」。

 半分、解けた。残りの、半分。決めるのは、桜子じゃない。

 送信ボタンに、指を置いた。

 手が、思ったよりは、震えていなかった。

 送信。


 遥の返信は、十分後に来た。

@yamashita-haruka: 桜子さん、整理、ありがとう。
質問の構成、すごく読みやすい。
チーム方針、実は、決まってない。
sakura-utils v1系を内製ツール (運用コンソール) で
踏んでる箇所があったはず。
明日の朝会で議題にしよう。
それまで、桜子さんの v2 化PRは、ドラフトのまま置いといて

 桜子は、画面の中で、ドラフトのまま置いといて、の一行を、ゆっくり読み直した。

 ドラフト、という言葉が、こんなにも、優しく見えた日は、なかった。


 通路を歩いていた鈴木が、桜子の机のそばを通り過ぎながら、Issueボードを覗いた。

「桜子さん、Issue起票、自分でやってくれたんだ」

「あ、はい。初めて、起票テンプレートを、使いました」

「ふんふん、目的 / 完了条件 / 担当。いいね。これ、定着してくれると、僕、めちゃくちゃ助かる」

「……はい」

 鈴木は、コーヒーカップを、軽く挙げて、自分の席に戻っていった。


Ending

シーン7 退勤前のメモ帳

 十九時。

 退勤前、桜子は、机の上のメモ帳を、もう一度、開いた。

 今日のページは、ふだんの「新人日記」より、すこしだけ、書く量が多くなっていた。

2022/06/07 新人日記

- 起きたこと:
  Issue #214 (sakura-core v2 化) で、SolverProblemError
- 覚えたこと:
  poetry の ^ 記号は、メジャーバージョンを跨がない。
  ^1.5.0 は >=1.5.0, <2.0.0
- つかえているところ:
  sakura-utils v1 系を内製ツールが踏んでいるかもしれない問題は、
  自分では決められない。明日の朝会
- 明日の最初の一手:
  朝会で、チーム方針が決まったら、PRをドラフトから上げる

 桜子は、いつもの五行の下に、もう一行、わざわざ、線を引いて、書き足した。

- 今日の学び:
  ひとりで読めないログは、紙に並べると、半分は読める。
  残りの半分は、聞く。それが、たぶん、最低限の作法

 ペン先を、置いた。

 桜子は、自分の机の引き出しから、境界条件バグの障害報告のコピーを、一枚だけ取り出した。あの日の、ふるえながら書いた、自分の障害報告。「学び:エラーは隠すより共有したほうが早い」。

 今日の、紙に並べると、半分は読める。

 二週間で、ほんのすこしだけ、桜子の側で、行が、増えた。

 (増やしていけば、いいんだ)

 桜子は、メモ帳を閉じて、退勤の準備を始めた。

 窓の外、梅雨入り目前の、灰色の空。

 帰り道の電車の中で、桜子は、ふと、もう一度、SlackのDMを開いた。遥の ドラフトのまま置いといて の一行を、もう一度、読んだ。

 (明日、朝会で、聞く)

 今日、聞かなかったわけじゃない。今日は、聞く前に、紙に書いたから、聞き方が、変わった。それだけのことだった。

 でも、それだけのことが、桜子の側で、何かを、ひとつだけ、軽くした。