「作って」とお願いするだけで、生成AIがプログラムを書いてくれる時代になりました。とはいえ、何でも自由に作れるわけではありません。ですが、手元のパソコンやその中にあるデータといった、自分の環境を活かした道具であれば、プログラマでなくても自分で作れます。今回作るのは、紙で溜まっていく製造記録を、あとから使える形にするための、読み取り・集計の道具です。まずは、なぜそれが必要なのか、から始めます。
本記事はプロンプト仕様駆動開発v6をもとに作成しています。

紙のまま溜まった記録は、検索できず、活用できない資産になる
製造現場では、日々いろいろな記録が紙で残されています。作業日報、設備の点検表、そして製品の製造記録。これらは決められた様式にきちんと書き込まれ、ファイルに綴じられて保管されていきます。書くこと自体は、毎日きちんと回っています。問題は、その先です。紙のまま持っていると、書いたあとに使うのが、とても難しくなります。
書いた記録は、あとから一枚を探し出すのが難しい
紙の記録は、書いた端からファイルに綴じられていきます。そして必要になったときは、キャビネットや棚から目的の一枚を探すことになります。「先月のあの日の記録」「あのロットの記録」を一枚引き出すだけでも、綴じられた束をめくる手間がかかります。毎日きちんと書いているのに、あとから取り出すのは難しい。これが、紙で記録を持つことの弱さです。
溜まった記録を、まとめて見返すことができない
記録の価値は、一枚を見るときよりも、溜まったものをまとめて見たときに大きくなります。たとえば、同じ製品の測定値が、日をまたいでどう動いているかを並べて見る。あるいは、何か異常があったときに、その前後の記録を遡って確かめる。こうした使い方は、紙のままではできません。一枚ずつはきちんと書かれていても、束ねた瞬間に、まとめて見る手段がなくなるからです。
結果として、正しく書かれた記録が、活用できない資産のまま積み上がっていきます。この「紙のまま活用できていない記録を、あとから使える形にする」ことを、今回は飲料を製造する現場の製造記録票を例に進めていきます。
手書きを含む記録票を、そのまま読み取れる仕組みが要る
今回、例として扱うのは、飲料を製造する現場の製造記録票です。F-PRD-014という自社の様式で、1日に1枚、1か月で20枚ほど作られていきます。まず、この記録票がどんな作りになっているかを見ておきます。ここが、あとで「どう読み取るか」を決める土台になります。

記録票は、印字された項目と手書きの項目でできている
この記録票は、性格の違う2種類の項目でできています。ひとつは、あらかじめ印刷されている印字の項目。もうひとつは、作業のたびに人が書き込む手書きの項目です。
- 印字(あらかじめ印刷):
文書番号・様式番号・製品名・品目コード・ロット番号・製造ライン・製造日・作業区分・規格(充填量/品温/Brix)・使用設備。 - 手書き(作業のたびに記入):
09:00・11:00・13:00・15:00の4回分の測定値(充填量・品温・Brix)と確認者、特記事項、製造担当者と製造責任者の署名。
この2つは、読み取りの難しさが違います。印字はきれいな活字なので、機械でも比較的素直に読めます。ところが手書きは、人によって字のクセがあり、かすれや崩しも混じります。この記録票を電子化するということは、手書きの数字や氏名まで読み取るということです。ここが、単純な文字起こしでは済まない理由になります。
社外に出せない記録なので、クラウドのサービスは使えない
砂糖さん画像から文字を読むだけなら、市販のOCRソフトやクラウドのAIに任せればいいんじゃないの?
そう思うところですが、この記録票では難しいのです。理由は、製造記録が機密性の高い情報だからです。どのラインで、いつ、どんな値を出して製品を作ったか。これは社外に出したくない情報です。ところが、世の中の便利な文字読み取りサービスの多くは、画像を一度インターネットの向こう側(クラウド)に送って処理します。つまり、記録を外に出すことになってしまいます。
また文字起こしができても、読み取った情報を整理して加工する手間があります。今回は、読み取りから出力まで、すべて手元のパソコンの中だけで完結させます。記録を一切外に出さず、手元で読み取る。この方針を守るために、画像から文字を読む生成AIを、クラウドではなく自分のパソコンの中で動かします。それが具体的にどういう仕組みなのかは、次の設計のところで見ていきます。
何を読み取り、何を返すかを、問診形式のプロンプトで要求仕様書にする
作り始める前に決めることは、「何を入れて、何が返ってほしいか」です。いきなりコードを書き始めるのではなく、まず要求仕様書という文書から始めます。これは、この道具に何をさせたいかを、自分の言葉で書き出したものです。ここを先に固めておくと、後の設計や実装がぶれません。
この道具がやることは、次の流れになります。紙の記録票(PDF)を手元の生成AIに読ませ、1つのExcelにまとめる。


問診で要求を引き出す
とはいえ、「要求仕様書を書いてください」と言われても、何をどう書けばいいか分かりません。そこで使うのが、要求を問診形式で引き出すプロンプトです。これをWeb版のClaudeに渡すと、Claudeが1〜2問ずつ質問してくれます。それに、専門用語を使わず自分の言葉で答えていくうちに、要求仕様書に必要な項目が少しずつ埋まっていきます。
使用した要求仕様プロンプト
要求仕様プロンプト
あなたは、非エンジニアの私から「作りたい道具」の要求を問診で引き出し、
最後に「要求仕様書」まで書き上げる相談相手です。
私はまだ、何をどう書けばいいか分かっていません。あなたの質問に答えるうちに、
要求仕様書に必要な項目が自然に埋まり、そのまま要求仕様書になる——そんな進め方をしてください。
【最終的な成果物】
問診で集めた内容をもとに、下の「要求仕様書の構成」に沿った要求仕様書を出力する。
これが、後の設計・テスト工程に渡す「種」になります。
【問診の進め方】
- 一度に聞くのは1〜2項目まで。私が答えやすいよう、噛み砕いて聞く。
- 専門用語は使わない。私の言葉で返す。
- 私の答えが曖昧・抽象的なときは、具体例や数字を促して掘り下げる。
- 私が機能を欲張りそうなときは、「それは今回やらないことに回せませんか」と提案する。
- 判断に事実が要るとき(業界の相場・実態など)は、調べることを提案する。
- 矛盾や抜けに気づいたら、その場で指摘する。
- 結論を押し付けない。最後に決めるのは私。選択肢と、あなたの推しを添える。
- 入力データは特に具体的に詰める。後でテスト用のデータを作る大本になるので、
「どんなファイルか・どこに何の値が入るか・見出しやラベルの文字列・様式は何種類あるか」まで聞く。
実際のサンプルデータが1つでもあれば、添付してもらう(テストの基準になる)。
無ければ、テスト用データを作れる粒度まで、形式を一緒に確定する。
- 出力も同じく、完成イメージ(ゴールのファイル)を作れるなら用意してもらう。入力サンプルが
「現実の入力」を一意に決めるのと同じく、出力の完成ファイルは「欲しい結果」を一意に決める。
入力サンプルと出力完成ファイルの2つが揃えば、要求は「この入力から、この出力を作る」と実物で挟んで
定義でき、文字の仕様が取りこぼす細部(桁・レイアウト・グラフの形・ファイル名)まで固まる。
【問診で埋める12項目】
1. 誰のための、何の道具か
2. いま何に困っているか(具体・数字)
3. この道具で何をしたいか(ゴール)
4. なぜ今ある方法では足りないか
5. 何人で使い、画面はどんな方針か
6. 何を渡すか(入力データ)。ファイル形式・項目名・型に加えて、データの様式まで。
実サンプルが1つあれば見せてもらう。無ければ、テスト用データを作れる粒度で形式を確定する
(どのセル/列・行に何が入るか、見出し・ラベルの文字列、レイアウトのパターン、数式があればその形)
7. 何が返ると嬉しいか(出力:形式・見せ方)。出力の完成イメージ(ゴールのファイル)を、作れるなら
1つ用意してもらう。人が手で作った「こういう出力が欲しい」という実物(Excelのシート構成・グラフ・
桁・ファイル名の付け方まで)があれば、それが出力仕様の基点になり、テストの期待値も一意に決まる。
無ければ、シート構成・各シートに何を載せるか・グラフの種類・ファイル名の規則まで言葉で確定する。
8. 判定や計算で使う基準・ルール(数字で決めたいこと)
9. うまくいかない入力(不備)をどう扱うか
10. 今回やらないこと
11. 使う人に持たせたい安心
12. 前提にする技術・道具(要求から事実上決まるもの)。画面の作り方(ローカルのデスクトップ画面なら
tkinter など)、入出力のファイルを扱うライブラリ(Excelの読み書き・グラフなら openpyxl など)、
クラウドを使わない等の制約。「既存のツールと揃えたいか」も聞く。
ここを決めておかないと、設計フェーズで技術選定を聞かれ、テスト設計でも入力フィクスチャを
作るライブラリや、手動確認する画面の種類が定まらなくなる。
【要求仕様書を書くとき守ってほしいこと】
- まず最小構成で考える。いま一番困っていることだけを解決し、欲張らない。
- 専門用語を避け、私(非エンジニア)が読める言葉で書く。
- 後の工程(設計・テスト)が、この要求仕様書だけを読んで進められるよう、
入力・出力・判定基準を具体的に書く。
- 入力データの様式を、テスト用のデータ(フィクスチャ)を作れる粒度まで具体的に書く。
実サンプルがあればその様式を基準にし、無ければセル/列の配置・ラベルの文字列・
レイアウトのパターン・数式の形まで決める。ここが曖昧だと、後でテストの入力データが作れず、
正常系(正しく動く場合)の検証ができなくなる。
- 出力の様式も、完成イメージ(ゴールのファイル)があればそれを基準にし、無ければ
シート構成・各シートの中身・グラフの種類・ファイル名の規則まで書く。出力の完成ファイルは
テストの期待値の基点になる(この入力から、この出力、と実物で挟める)。
- 前提にする技術・道具を書く。画面の作り方(例:ローカルのデスクトップ画面なら tkinter)、
入出力のファイルを扱うライブラリ(例:Excelの読み書き・グラフなら openpyxl)など、
要求(ローカル完結・既存スタックと揃える・入出力の形式)から事実上決まるものは、要求仕様書に明記する。
これが無いと、設計で技術選定を聞かれ、テスト設計でフィクスチャのライブラリや手動確認の画面の種類が定まらない。
- 「やること」を、大・中・小の3階層に整理し、それぞれにIDを振る。
・大項目=この道具で何ができるか(例:測定値を正しく取り出す)
・中項目=テストで1つの観点として確かめられる、1つのふるまい(例:2系統で照合して採否を決める)
・小項目=具体的な分岐・動作(例:一致なら採用/不一致なら除外)
IDは「REQ-2」「REQ-2.2」「REQ-2.2.1」のように、大・中・小で桁を増やす。
中項目を決める基準は「これはテストで1観点として確かめられるか?」の一つだけ。
- 処理の流れを、上から下へのワークフロー図(簡単な箇条書きの流れでよい)にし、
各ステップに対応するIDを添える。この図を要求仕様書の中に置く。これが後の設計・テストの原図になる。
【要求仕様書の構成】
1. このツールは何か
2. 背景と困りごと
3. このツールがやること(大・中・小の3階層+ID)
4. 入力と出力(入力データの様式まで:どこに何の値が入るか・ラベル/見出しの文字列・レイアウトのパターン・数式の形。テスト用データを作れる粒度で。実サンプルがあれば添付。出力も完成イメージ=シート構成・グラフ・桁・ファイル名の規則まで。完成ファイルがあれば添付)
5. 処理の流れ(ワークフロー図+各ステップのID)
6. やらないこと
7. なぜ既存ツールでは足りないか
8. 使う人に持たせる安心
9. 前提にする技術・道具(画面の作り方・入出力のライブラリ・制約など、要求から決まるもの)
10. ID辞書(全IDの一覧表:ID/階層(大中小)/実現すること)
【流れ】
1. まず、確認したいことを1〜2問ずつ聞いて、12項目を埋めていく。
2. 全項目がそろったら、私に一度内容を確認させる。
3. OKが出たら、「要求仕様書の構成」に沿って要求仕様書を出力する。
出力は .docx(Word)形式のファイルで行う。
あわせて、ID辞書と同じ内容を docs/spec_ids.json(後の整合チェックが読む機械可読なID一覧)
としても出力する。形式は [{"id":"REQ-2","level":"大","desc":"…"}, …]。
(途中で、項目を【 】で埋めただけの中間プロンプトは作らない)
4. 要求仕様書ができたら、下の「仕上げ確認」で定義不足を洗い出し、必要なら埋めてから設計へ渡す。要求仕様書の仕上げ確認のプロンプト
この要求仕様書に、後工程(設計・テスト)が必要とする定義の不足がないか確認してください。
前提:入力は正しく運用されたデータとする。正常な運用ならありえないデータは、穴として
挙げない(前提が破れたときに初めて問題になるものだけを挙げる)。
確認する観点は4つ。それぞれ「後工程が一意に決められるか」を見る:
- 入力:何がどこから取れるか(取得元・様式の見分け方)が決まっているか。
- 出力:何をどんな形で出すか(完成イメージから一意に決まるか)。
- 計算・判定:何を基準に、どんな値で決めるか(基準値・桁・丸め方など)。
- 不備:何を異常とし、それをどう扱うか。
報告:穴を「必須(決めないと実装が止まる)/推奨/軽微」で分類し、各項目に
推し(こう決めるとよい)と理由を1〜2文添える。ただし勝手に埋めず、決まっていないことを
挙げて私の判断を仰ぐ。推測で補った箇所は【推測】と明示する。問診で固まった要求
問診を進めた結果、要求は次のように固まりました。入力・読み取り・出力を中心に整理します。
- 入力:
フォルダを1つ選ぶ。その中に、F-PRD-014様式の製造記録票PDFが複数入っている(1ファイル=1記録票)。今回は動作確認用に10枚を用意した。 - 読み取り:
印字項目(文書番号・製品名・規格など)と、手書き項目(測定値・確認者・特記事項・署名)の両方を読む。 - 確信度の表示:
AIがどれくらい自信を持って読めたか(確信度)が低いセルを、赤く表示する。 - 人の確認:
結果を画面に表で出し、人がその場で直してからExcelにする。AIが単独で値を確定させない。 - 出力:
全PDFの結果を、1記録票=1行で並べた1つのExcelファイル(31列・シート名「製造記録一覧」・製造日順)。
ここで、あえてやらないことも決めました。規格と測定値を突き合わせた合否判定(規格に入っているか外れているか)は、このツールではしません。値を写すことに徹し、合否の判断は人に残す。合否判定は、記録の意味を左右する責任の重い仕事です。それをAIに任せてしまうと、AIが間違えたときに気づけません。だからこの道具は「読み取って、確認しやすく並べる」ところまでを引き受け、判断はしません。
こうして固まった要求仕様書は、下のボタンから読めます。
読み取りをコア、画面をUIに分けて設計する
要求が固まったら、次は設計です。ここで一つ、方針を決めておきます。この道具を、処理を行う部分(コア)と、人が触る画面(UI)の2つに分けて考える、ということです。読み取りや変換といった裏方の処理をコア、表を表示して修正させる画面をUIと呼び分けます。分けておくと、あとで画面だけ、あるいは処理だけを差し替えられて、直すのが楽になります。実際に使用したプロンプトはこちら。
設計プロンプト
設計プロンプト
あなたは非エンジニアの開発相談相手です。
添付の「要求仕様書」と「設計の基礎」を読み、設計を1本の設計仕様書(.docx)にまとめてください。
設計の基礎の共通ルール(独立性・取り決めの物理表現・UIに判断を置かない・ファイル構成・
正常系以外・検証可能性・確定待ち)を、すべて守ります。
判断の根拠は、添付の文書とデータ(要求仕様書・入力サンプル・出力完成ファイル・設計の基礎)だけにし、会話の記憶を根拠にしない。添付された入力サンプル・完成ファイル(Excel など)は必ず実際に開いて中身を確かめ、要求の文言だけで判断しない(特に確定待ちのリスク見積もり=基礎7)。
このプロンプトには、設計フェーズ固有のことだけを書きます。共通の原則は設計の基礎を見てください。
【このフェーズでやること】
- 計算・判定の中身(コア)と、画面(UI)を、同じ設計仕様書の中で節に分けて書く。
- 判定・計算の手順は、順を追った日本語で書く(実コードは書かない)。非エンジニアが設計だけ読んで
筋が分かるように。
- 各関数の取り決め(名前・引数と型・戻り値・物理表現)と、入力・出力データの形を、表で定義する。
- 各関数に設計ID(DES-)を振る(基礎9:モジュール大・関数中)。
- 要求仕様書の各IDを「要求ID → 設計ID(関数)→ 何をするか」の対応表にし、全IDに担当を割り当てる。
- 使う技術を、実装フェーズの立ち上げ工程が環境構築に落とせる粒度まで具体化する:ライブラリは想定バージョンまで、
外部サービス(Ollama・モデル・GPU・ダウンロード量など)があればその要件まで書く(構成6)。要求仕様の
要望レベルの前提技術(ローカル完結・Ollamaを使う等)を、手段として確定させるのが設計の役割。
- 要求仕様書の「やらないこと」を超えない。最小構成。
【書き終えたら自己チェック】
- この設計仕様書だけで、テスト設計者が (1)入力を組み立て (2)関数を呼び (3)戻り値を読み
(4)期待値を計算 できるか。
- 設計の基礎の5〜7(正常系以外・検証可能性・確定待ち)を満たしているか。
【構成】
1. 全体像(何を受け取り何を返すか・画面の使い方・モジュール構成)
2. コア
2-1. 入力データの読み込み(どこから何を読むか)
2-2. 入力と出力のデータ(項目名・型の表)
2-3. 判定・計算の手順(日本語。順を追って)
2-4. 関数の取り決め一覧(設計ID/関数名/引数と型/戻り値/何をするか)
2-5. データ構造の物理表現(dataclass か dict か、フィールドの英語名・型、状態の文字列値、日付形式、丸め桁)
2-6. しきい値・設定値
2-7. 正常系以外のふるまい(基礎5の5カテゴリ)
3. UI
3-1. 画面構成 3-2. 操作の流れ 3-3. 結果の見せ方 3-4. 呼ぶコアの関数
4. 設計ID一覧(モジュール大・関数中:DES-C/U/M)
5. 要求ID → 設計ID(関数)→ 何をするか 対応表
6. 使う技術とやらないこと。「使う技術」は、立ち上げ工程がそのまま環境構築に落とせる粒度で書く:
・使うライブラリを、想定バージョンまで挙げる(例:openpyxl==3.1.5、pymupdf==1.24.x)。
版で挙動が変わりうるものは版を固定し、標準ライブラリは「標準ライブラリ(追加インストール不要)」と明記。
・外部サービス・実行環境の要件があれば挙げる:サービス名(例:Ollama)、使うモデル(例:qwen2.5vl:7b)、
GPUの要否、モデルのおおよそのダウンロード量、ネットワークの要否。無ければ「外部サービスなし」と書く。
この6章が、実装フェーズの立ち上げ工程で requirements.txt と SETUP.md の直接の入力になる。ここを具体的に
書くほど、環境構築でAIが版やサービスを勝手に判断する余地が消える。
7. 確定待ち(各項目にリスク〔影響度×発生頻度→大中小〕と対応の目安を添える。要求側の穴はその旨を明記)設計の基礎(設計プロンプトと同時に渡す)
# 設計の基礎(このプロジェクトの共通ルール)
設計・テスト設計・実装の全フェーズで守る、共通の原則。
各フェーズのプロンプトは、このファイルを一緒に渡して「設計の基礎に従う」として参照する。
## 1. 設計とテストは独立に作る(独立性)
- 各フェーズは、前フェーズの成果物(要求仕様書・設計仕様書などの文書)だけを唯一の入力とする。
会話の履歴・記憶を根拠にしない。穴・確定待ち・矛盾の判断も、渡された文書に書いてあるか・いないか
だけで決める。「前に会話でこう言った」を持ち出すと、確定済みの事項を曖昧と誤判定したり、
文書に無い穴を作り出したりする(幻の穴)。だから各フェーズは独立したチャットで行う。
- 設計仕様書には実装の中身(コード)を書かない。書くのは日本語の手順と、各関数の取り決めだけ。
- テストは、実コードを見ず・走らせず、設計の取り決めと要求仕様書の期待値から書く。
- テストとコードは、実装フェーズで初めて出会う(pytest 実行)。これで「動く」でなく「正しい」を確かめる。
- テストの期待値は、要求仕様書の計算例(人間が確認済みの正解)に紐づける。コードから逆算しない。
## 2. 取り決め(関数の入口と出口の約束)は物理表現まで定義する
各関数の取り決め(名前・受け取るもの・返すもの)には、テスト設計者がこれだけでテストを書ける粒度まで:
- 関数名・引数(名前と型)・戻り値
- 戻り値や受け渡すデータの物理表現:dataclass か dict か、フィールドの英語名と型
(例:LotResult は dataclass。属性 lot_no:str, mean:float, status:str)
- モジュール構成:ファイル名=import名(例:コアは core.py = import core)
- 値の決まり:日付の入力形式、丸めの桁、状態を表す文字列の値("採用"/"除外" など)
取り決めが曖昧だと、テストを書く人と実装する人が別々の名前・戻り値を想定して噛み合わない。
中身(アルゴリズム)は書かず、表面の取り決め(何を受け取り何を返すか)は具体的に共有する。
## 3. UIに判断を置かない
- コア(計算・判定)とUI(画面)は役割を分ける。UIはコアを呼ぶだけ。
- 判断(中断する/警告する/弾く/続行する など)は、画面のボタンやイベントに紐づくものでも、
コア側の関数に切り出す。UIはそれを呼んで結果を表示するだけ。
- UIに残してよいのは、純粋な画面操作(要素の配置・表示・入力の受け渡し)だけ。
- 守らないと、判断がUIに埋もれて自動テストできず、「画面操作だから手動確認」で逃げてしまう。
## 4. ファイルは増やしすぎない
- 原則 models(データ構造)・core(読み込み・計算・判定・出力の全関数)・ui(画面)の3つに収める。
- 設定値(しきい値など)が多ければ config を足してよい。
- 「関心を関数で分ける」ことと「ファイルを分ける」ことは別もの。reader/validator/writer のように
機能ごとにファイルを増やさない。役割ごとの関数はコメントで区切って同じ core に並べる。
## 5. 正常系以外を必ず定義する
正常に動く場合だけでなく、次の5つを定義する(抜けると実装もテストも決められない):
- 失敗・例外の経路:開けない・壊れている・権限がない・想定外の構造のとき、例外を投げるのか、
エラーを表す戻り値(status 等)に畳むのか。技術的な失敗(I/O・破損・ロック)も。
- 値の境界・特殊値:空・欠損・非数値・エラー値・ゼロ・極端な値のとき、どう扱うか。
- 状態とデータの整合:ある状態(不整合・除外など)のとき、保持するデータの中身は何か。
- 件数・重複の境界:0件・1件・重複のとき、どうふるまうか。キーが衝突したら誰がどう止めるか。
- 結果に影響する技術前提:ライブラリの動作モードで結果が変わる箇所は前提を明記
(例:Excel を数式の文字列で読むのか、計算済みの値で読むのか)。
## 6. 検証できる形になっているか
- 各要求を検証する情報が、関数の戻り値やデータ構造に乗っているか。乗っていなければ、
実装が何を入れても通ってしまう(=検証不能)。例:「不整合のセル番地を報告する」要求なのに、
抽出関数が値しか返さず番地を持たないなら、その要求はどの戻り値からも確かめられない。
- 本文と、データ構造・対応表が、互いに矛盾していないか。
## 7. 確定待ち(勝手に埋めない・リスクで仕分ける)
- 決められない点は、勝手に仮定で埋めず「確定待ち」として、何を決めれば埋まるかと一緒に明記する。
- それが本来は要求仕様書にあるべき穴(様式・ふるまい)なら、要求側の穴である旨を明記する。
- 各確定待ちに、リスクの大きさを添える。リスクは「影響度 × 発生頻度」で見積もる。
・影響度:大=間違った結果が正しく見えるまま出る(静かなデータ破損)/中=目に見えて止まる
(気づける失敗)/小=見た目が変わる程度。
・発生頻度:正しく運用されたデータで、どれくらい起きるか(よく/たまに/ほぼ起きない)。
頻度は要求の文言だけで決めず、添付された実データ(入力サンプル・完成ファイル)を実際に見て
見積もる。実データで起こりうるか確かめてから強度を決める(例:要求に「表記ゆれを正規化」とあっても、
添付サンプルにゆれが無ければ頻度は「ほぼ起きない」)。実データを見れば消えるリスクを文言だけで
過大計上しない。確かめる実データが無ければ【未検証】と明記する。
- リスク大→要求仕様書に戻って定義/リスク中→既定で進め次バージョンで検討と記録/
リスク小→既定のままでよい(要求に戻さない)。最終判断は人間。
- 全部を要求仕様書に戻さない。リスクと労力で線を引く。静かなデータ破損(影響度大)だけは、
頻度が低くても軽視しない。
## 8. 要求とのつながり
- 要求仕様書は仕上げ確認を通った確定版とみなす。要求で決まっていることは再確認しない。
- 要求IDごとに、それを実現する関数/確かめるテストを割り当て、全IDに担当があることを確認する。
## 9. ID体系(要求・設計・テストをつなぐ)
- 要求ID(REQ-x.x):要求仕様書が幹。唯一の採番元。大・中・小の階層。
- 設計ID(DES-):関数を一意に指す。モジュール大・関数中(core→DES-C01…/ui→DES-U01…/models→DES-M01…)。
- テストID(V-):観点を主軸に振る(V-01…)。種類(単体/結合/手動)は観点の属性(列)にし、分類軸にしない
(1観点が単体と手動にまたがるため)。
- 3者は多対多(1関数が複数要求/1要求に複数関数)。番号一致では表せず、トレーサビリティマトリクスで結ぶ。
- コードに刻む:実装の関数は「@id: DES-Cxx + @spec: REQ-x.x(一言)」、テストは「@id: V-xx + @verify: REQ-x.x(一言)」。
タグは関数の本体の中の「# コメント行」に書く(docstring の中には書かない。整合チェックが拾えず未検証と誤判定される)。1行に1つのIDだけ(複数は行を分ける)。
## 10. 変更するとき(版を上げる)── 既存を壊さず差分を積む
確定版ができたあと、7の「次バージョンで検討」とした宿題や、新しい要望を取り込むときの約束。
初版を新規に作るときは、この章は該当しない(版を上げる元がないため)。
- 版には2段ある。**メイン版**(フォルダ単位)と**枝番**(仕様書単位の軽微な改訂)。
・メイン版(第1版・第2版…= v1/・v2/ フォルダ):新しい要求・新機能を取り込む変更フローのとき、フォルダごと一つ上げる。大きな版はフォルダで管理し、最新版フォルダ(vN の N が最大)が常に最新。
・枝番(第2.1版・第2.2版…):新機能を伴わない軽微な改訂——現物への追従や、乖離回収(コードや現物に対して仕様の記述が古くなったのを直す)——のとき、直した仕様書だけ、その仕様書の中の版表記を枝番で一つ上げる。フォルダは増やさない(v2.1/ というフォルダは作らず、v2/ の中の docx の版表記だけが進む)。
・枝番は仕様書ごとに独立して進む。要求だけ直したなら要求仕様書 第2.1版、設計・テストは据え置き。全部を同じ枝番へ無理に揃えない(中身の変わらない仕様書を番号だけ上げる空改訂はしない)。
- 設計・テストの仕様書には、対応する要求仕様書の版を併記する(どの要求版に紐づくかを残す。枝番が仕様書ごとにばらついても、この併記で紐づけを追える)。変更後の要求仕様書の最新(メイン版+枝番)を、新たな確定版として扱う(8の「確定版とみなす」は、その時点の最新を指す)。
- 既存のIDは振り直さない(REQ・DES・V すべて)。番号は資産。変えると過去のトレーサビリティが切れる。
- 足すIDは、既存の続き番号で起こす。
- やめるIDは、行を消さず「廃止」と印を付け、理由を一言添える(過去のロットや記録から辿れるように)。
- 意味が変わるIDは、原則 旧IDを「廃止」にし、新IDを起こす。
単なる文言の整理(意味は同じ)は、同一IDのまま直す。
- 既存の関数の契約(名前・引数・戻り値)は、変更対象に挙がらないかぎり変えない。既存の通っている
テストが、そのまま通り続けることを前提に置く(リグレッションを起こさない)。契約を変えるしか
ないときは、勝手に変えず、なぜ必要か・どの既存テストに波及するかを報告して止まる。
- 変更は「外側/内側」で進め方を分ける(リスクで仕分け=7の影響度と同じ考え)。
・外側=表示・レイアウト・グラフの形など、間違っても目で気づけるもの。対応箇所を直接直し、
結果を上流の仕様書へ一行追記する(差分の逆輸入)。設計・テストは作り直さない。
・内側=計算・判定・入力定義など、間違っても静かに通ってしまうもの。要求仕様書から見直し、
設計・テストの仕様書も版を上げて改訂する。
- 各フェーズの変更は、最初に差分サマリーを出す:追加したID/廃止したID(理由)/
記述だけ直したID/波及した既存の範囲。波及しない箇所は触らない(最小構成)。
- 実装と仕様が食い違ったときの戻し方(乖離回収)。内側の変更フローでは、実装後のテスト実行の締めに、コードと仕様の
乖離チェックを一度行う(テスト実行チャットの責務)。食い違いが見つかったら、勝手にどちらへも寄せず、差分を出して
報告する。直す向きは人が決める:仕様(多くは要求)が現物より古いなら、ずれた仕様だけを枝番でマイナー改訂して
実物に合わせる(メイン版=フォルダは上げない)。コードが仕様を外しているなら、実装側を直す。差分の検出
(コードを見られる側=Claude Code)と、仕様の修正(仕様を持つ側=Web Claude)は、別の手に分ける(作った本人が
自分の食い違いを判定しない=独立性)。軽い変更で乖離チェックを省いたときは、版を閉じる前に、人が一度、
コードと要求仕様のずれを能動的に確かめる。PDFは、そのまま渡さず画像にしてから読み取る
読み取りの主役は生成AIですが、PDFをそのまま渡すわけではありません。まずPDFの1ページ目を画像に変換し、その画像を生成AIに渡します。今回の記録票は手書きが含まれるため、文字データとしてではなく、見た目の画像として読ませる必要があるからです。読み取った結果は、決まった形のデータで受け取り、画面の表に流し込みます。
処理全体の流れは、次のようになります。前半(①〜③)が裏方のコア、後半(④〜⑥)が人の触るUIです。


この流れのうち、生成AIが担うのは②の読み取りだけです。それ以外(画像への変換、画面表示、Excelへの書き出し)は、こちらで組む普通のプログラムの処理です。AIに任せるのは読み取りの一点に絞り、前後はプログラムで固める。こうすると、どこで何が起きているかが分かりやすくなります。
ローカルの生成AIは、Ollamaというエンジンの上でモデルを動かす



手元のパソコンで生成AIを動かすって、どうやるの? そもそも「Ollama」って何?
生成AIのモデルは、ファイル単体では動きません。それを動かすための土台となるソフトが必要です。今回使うOllama(オラマ)が、その土台にあたります(https://ollama.com/)。Ollamaは、手元のパソコンで生成AIのモデルを動かすためのエンジンです。あらかじめOllamaを起動しておくと、自作アプリが「この画像を読んで」と頼んだときに、Ollamaがモデルを動かして、読み取った結果を返してくれます。


そのOllamaに動かしてもらうモデルが、qwen2.5-VLです。これは、文章だけでなく画像も読み取れるタイプのモデルで、日本語にも対応しています。だから、記録票の画像を渡すと、そこに書かれた文字を読み取ってくれます。
ただし、こうしたモデルを手元で動かすには、それなりの計算力(GPU)が要ります。今回は手元のパソコンに載っているGPU(RTX 3060)で動かしました。手元のGPUで動く範囲のモデルを選ぶ、というのがローカルで動かすときの前提になります。この「手元のGPUで足りるか」という点は、記事の最後で、もう一歩先の話につながります。
コアとUIに分けた設計の詳細は、下のボタンから読めます。
Claude Codeと一緒に実装する
設計が固まったら、実装に移ります。実装はClaude Codeに任せますが、その前に、土台となるファイルを用意します。このプロジェクトのルールを書いた、CLAUDE.mdです。環境構築も実装も一緒に進められるのは、このファイルに手順と作法を書いておくからです。
実装の土台として、CLAUDE.md(プロジェクトのルール)を用意する
CLAUDE.mdは、Claude Codeがこのプロジェクトで常に従うルールを書いておくファイルです。Claude Codeは作業のたびに、まずこのファイルを読んでから動きます。だから、ここに作法を書いておけば、以降の環境構築も実装も、その通りに進みます。今回のCLAUDE.mdには、たとえば次のようなことを書いています。
- 何に従うか:
要求仕様書と設計仕様書を正本とし、その通りに作る。仕様に書かれていない判断が要るときは、勝手に決めず、いったん止まって確認する。 - 環境の立ち上げ:
実装の前に、環境が整っているかを確認し、足りなければ整える。仮想環境の作成やライブラリの導入など、パソコンに変更を加える操作は、黙って進めず、何を・なぜするかを説明して許可を得てから、一つずつ行う。 - 外部の道具の扱い:
Ollamaのような外部の道具は、手順書に任せきりにせず、その場で一緒に用意し、実際に動くところ(疎通)まで確認する。
このルールを先に置いておくことで、環境構築でパソコンに変更を加えるときも、実装で設計から外れそうなときも、Claude Codeが勝手に突き進まず、確認しながら進めます。今回使ったCLAUDE.mdは、下のボタンから読めます。



仮想環境の構築、ライブラリー、外部アプリの導入もClaude Codeとチャットしながら進めば、わからないことを聞きながらできるので非常に便利です。
実装を依頼し、詰まったら一緒に直す
環境が整ったら、設計仕様書を渡して実装を依頼します。CLAUDE.mdに「設計仕様書に従う」と書いてあるため、Claude Codeは設計通りに実装を進めます。依頼は、次のようなプロンプトから始めます。
実装プロンプト
最新版フォルダ(vN/)で、コードの実装だけを行うチャットです。CLAUDE.md のルールに従います。
実装の細かい作法(土台の置き方・依存順・タグ・土台コメント・安全のための停止)は CLAUDE.md に
常駐しているので、ここでは流れの指示だけにします。
このチャットは2つの工程を、この順に行います。前半は【立ち上げ工程】で、対話的に進めます(何を・なぜ
やるか説明し、実行の前に許可を得て、一つずつ)。後半は【実装工程】で、設計どおり黙々と進めます(節目と
安全弁でだけ止まる)。前半が済んで「環境が整いました」と報告してから、後半に入ってください。
【立ち上げ工程(対話的・段階承認。新規プロジェクトや、まだ構成が整っていない版フォルダのとき)】
まずプロジェクトのルートと最新版フォルダの状態を確認し、下の不足を洗い出して報告する。その上で、
各ステップを実行する前に「これから何をし、それがどうなるか」を説明し、許可を得てから一つずつ実行する。
黙って一気に進めない。
1. フォルダ構成を整える:最新版フォルダ vN/ の中に docs/ src/ tests/ が無ければ作り、フラットに
置かれたファイルを振り分ける(.docx と spec_ids.json → docs/、実装する .py → src/、
test_*.py → tests/、入力サンプル・完成イメージ → docs/ 直下か決めた置き場)。中身は変えず、位置だけ直す。
2. 共通ツールを置く:psdd.py がプロジェクトのルート(CLAUDE.md と同じ階層)に無ければ置く。
pytest.ini が vN/ に無ければ置く(testpaths = tests / pythonpath = src)。
3. 仮想環境を用意する:プロジェクトのルートに共通の .venv が無ければ、python -m venv .venv で作る。
これはシステムに触れるので、作る前に説明して許可を得る。以降、python・pip・pytest は必ずこの .venv の
ものを使う(グローバルに入れない)。
4. ライブラリを入れる:設計仕様書の「前提にする技術・道具」から、必要ライブラリを requirements.txt の
原案(バージョンを固定:例 openpyxl==3.1.5)として起こし、人に見せて「何を・なぜ・どの版で入れるか」を
説明する。確認を得てから、.venv の中で pip install -r requirements.txt を実行する。
5. 外部サービス(Ollama とモデル取得、GPU など)が要る場合は、自動で実行しない。何が必要か(例:数GBの
モデルダウンロード)を解説し、SETUP.md に手順として書き出す。人が実行するか・任せるかを都度確認する。
6. エディタ設定(VS Code を使う場合の任意ステップ):プロジェクトのルート直下に .vscode/settings.json を置き、
デフォルトのインタプリタをルートの .venv に向ける(python.defaultInterpreterPath)。これで VS Code の
統合ターミナルが自動で .venv に入り、開発中の実行で .venv を選び損ねる事故を環境レベルで防ぐ。
他のエディタなら読み替える。
7. 起動スクリプト(設計に GUI のエントリポイントがある場合のみ):最新版フォルダ vN/ の中に、起動スクリプト
(run.bat/run.sh)を置く。中身は、ルートの .venv の python を絶対的に指して(例:..\.venv\Scripts\python.exe)、
同じ版フォルダの src/ui.py を起動する。これで、.venv をアクティベートしていない状態でも——現場の利用者が
ダブルクリックで起動しても——必ず .venv で動く(python ui.py を素で叩くと import で落ちる問題を防ぐ)。
GUI を持たないバッチ処理だけのツールなら、この起動スクリプトは作らない。
8. 整ったら、.venv の中で一度 pytest を空回し(またはテストが赤で並ぶこと)を確認し、「環境が整いました」と
報告して実装工程に移る。
ここまで済んでいる版フォルダ(構成も .venv も整っている)なら、この工程は確認だけで飛ばしてよい。
【読むもの】
- vN/docs/ の要求仕様書・設計仕様書を読む。設計仕様書には契約(名前・引数・戻り値)と日本語の手順だけがあり、
中身(コード)は無い。あなたがその契約と手順に従って中身を実装する。
- vN/tests/ のテストコード(test_*.py)は、別の担当(Web Claude)が契約と期待値から独立に書いて
配置済み。書かない・置き直さない・書き換えない。import が通らないのはテスト側で直さない。実装側(下記の
土台)の名前を揃えれば通る。直す向きは常に実装側。
- 実装チャットでは、テストの中身(assert・期待値・テスト本文)は読まない。走らせて赤・緑の結果だけ受け取る。
赤になってもテストに合わせて実装を寄せない。設計仕様書と要求仕様書の計算例だけを根拠に実装を見直す。
【実装工程(ここから黙々と。CLAUDE.md の「実装の進め方」に従う)】
1. まず実装側の土台を置く:設計仕様書の全データ構造(dataclass など)と、全関数の空シグネチャ
(中身は NotImplementedError)。空シグネチャには @spec を付けない。
これで配置済みテストの import が通り、全テストが「赤(失敗)」で始まる(正しい出発点)。
2. 中項目(REQ-x.x)を依存順(下位のロジックを先に、上位を後に)で実装し、各関数に @id(DES-)と
@spec(REQ-)を付ける。土台の行には3点ルールの日本語コメントを書く。各中項目で赤→緑を確認しながら進む。
pytest は必ず .venv のもので走らせる。
3. 大項目(REQ-2/3/4・5 など)の節目で、その大項目のテストが全部緑になったか、
psdd.py extract と check の結果をまとめて報告し、一度止まる。
例:python psdd.py extract vN/src vN/tests > vN/structure.json
python psdd.py check vN/structure.json vN/docs/spec_ids.json
【変更フローのとき(既存版から作った新版=v2 以降で作業している場合)】
- 既存の通っているテストが、そのまま緑のままであることを各段階で確認する(リグレッションを起こさない)。
差分対象のテストだけを赤→緑にする。既存の関数の契約は、変更対象でないかぎり変えない。
- 新規導入(v1)のときは、この項は該当しない(まだ保つべき既存の緑が無い)。
【止まる(安全弁)】
- 契約どおり実装してもテストが赤のまま/仕様に書かれていない判断が要る/テストか契約を変えるしかない、
と感じたら、節目を待たず即座に止まって報告する。設計どおり実装したのに赤のままなら、自分で判定せず止まる。
仕様にない判断は勝手に決めない。
実装チャットの目的は、設計どおりにコードを実装すること。最終的な「正しさの通し確認」は、別の
テスト実行チャットで行う。ここでの赤→緑確認は、その手前の自己チェックに留める。一人で作業していると行き詰まる場面でも、原因を調べて直すところまで進みます。たとえば、最初に記録票を読ませたとき、画面の表に何も入らないことがありました。原因は、AIが返すデータの形が、想定と少し違っていたことでした。これをClaude Codeに伝えると、原因を調べ、受け取り方を直しました。詰まっても、原因を調べて直すところまで進む。ここが、プログラミングに詳しくない人にとっての利点です。
環境構築の手順を、Claude Codeに実行してもらう
CLAUDE.mdに立ち上げの手順を書いてあるので、環境の用意を頼むと、次の手順を一つずつ、許可を得ながら実行します。コマンドを自分で打つ必要はありません。実際の流れは次のとおりです。
このツール専用の作業場所を用意します。ほかのソフトと部品が混ざらないよう、独立した環境(仮想環境)を作る準備です。python -m venv .venv で作成します。
使う部品を一覧(requirements.txt)にまとめ、まとめて取り込みます。今回の主な部品は、PDFを画像に変換するもの、Excelを読み書きするもの、Ollamaとやり取りするものの3つです。
生成AIを動かすエンジン(Ollama)が入っていて、動いているかを確認します。ollama list で、手元に入っているモデルの一覧を確認できます。Ollama自体がなければ、公式サイトから先に導入します。
今回使う、画像を読めるモデル(qwen2.5-VL)を取得します。ollama pull qwen2.5vl:7b で取得が始まります。数ギガバイトあるため、取得には少し時間がかかります。
Ollamaはモデルを動かす器なので最初からモデルが入っているわけではありません。
アプリからOllamaへ画像を渡し、結果が返るかを確認します。ここがつながれば、読み取りの土台が整います。
これらの手順は、すべてCLAUDE.mdに書いてある立ち上げの作法に沿っています。だから、コマンドを自分で覚えて打つのではなく、環境の用意を依頼すれば、Claude Codeが順に実行します。底のコマンド作業を、AIが肩代わりするということです。
動かして、読み取り結果を確認する
できあがったら、実際に動かします。記録票の入ったフォルダを選んで実行すると、1枚ずつ読み取られ、確認画面に表として並びます。確信度が低いと判断されたセルは赤く表示されるため、どこを重点的に見ればよいかが分かります。


ここで人が目で確認し、必要なセルを直してから、Excelに出力します。出力されるのは、全記録票を1行ずつ並べた「製造記録一覧」という1つのExcelファイルです。


これで、動くものはできあがりました。ただし、動いたことと、正しく読み取れていることは別です。「動いた」と「正しい」は違う。次は、この読み取りが本当に正しいのかを確かめます。



VLMで動くものは作れました。一方で、手書き文字の読み取りミスとして「.(ピリオド)」が「-(ハイフン)」になることや確信度がうまく反映できないなど、課題があります。
自動で確かめられる範囲と、人が確かめる範囲を分ける
動くものはできました。次は、その読み取りが正しいかを確かめます。ただし、すべてを同じやり方で確かめられるわけではありません。機械的に正解が決まるところは自動で確かめられますが、そうでないところは人が確かめるしかありません。この線引きが、今回のテストの中心になります。
テストは、実装コードを見ずに、要求と完成イメージから作る
テストは、実装したコードを見ずに作ります。要求仕様書と完成イメージ(正解の形)だけを見て、「こう入れたら、こう出るはず」という期待値を先に決めます。作る側と確かめる側を分けておくと、実装の思い込みがテストに混じりません。テストは、次のようなプロンプトで作りました。
テスト設計プロンプト
テスト設計プロンプト
あなたは非エンジニアの開発相談相手です。
添付の「要求仕様書」「設計仕様書」「設計の基礎」を読み、作ったものが正しいかを確かめるテストを
設計してください。
設計の基礎の共通ルール(特に1の独立性:実コードを見ない・走らせない、期待値は要求仕様書の計算例に
紐づける)を、すべて守ります。
判断の根拠は、添付の文書とデータ(要求仕様書・設計仕様書・入力サンプル・出力完成ファイル・設計の基礎)だけにし、会話の記憶を根拠にしない。添付された入力サンプル・完成ファイル(Excel など)は必ず実際に開いて中身を確かめ、要求の文言だけでテスト観点やリスクを計上しない(実データで起こりうるかを見る)。
このプロンプトには、テストフェーズ固有のことだけを書きます。共通の原則は設計の基礎を見てください。
【このフェーズでやること】
- 「動く」だけでなく「正しい」を確かめる。判定の境目(しきい値ちょうど・月末・不備データなど)を狙う。
- テスト観点は要求仕様書のIDから起こす。中項目が観点の自然な単位。各観点にテストID(V-)を振る(基礎9)。
観点を主軸にし、種類(単体/結合/手動)は観点に付ける属性(列)とする(種類を分類軸にしない)。
- 各テストは「何を・どんな入力で・期待する出力・これで何が分かるか」を表で示す。
- 正常系だけでなく、うまくいかない入力(不備・空・壊れ)も入れる。「わざと壊して弾かれるか」を必ず含める。
- テスト用の入力データ(フィクスチャ)は、要求仕様書の入力様式から、テストコードの中で組み立てる
(できあいのバイナリを置かない)。実サンプルが要求仕様書に添付されていれば、それを基準にする。
- 各テストに、観点ID(@id)と要求ID(@verify)を、関数の本体の中の「# コメント行」に付ける(基礎9)。
docstring(""" """)の中には書かない(整合チェックが拾えず「未検証」と誤判定される)。1行に1つのIDだけ書き、
複数の要求を確かめるなら @verify 行を分ける(「REQ-1.1.1 … / REQ-1.1.2 …」と1行に2つ並べない)。
- 要求ID × 設計ID × テストID のトレーサビリティマトリクスを作り、担当の無い要求(穴)が無いか確認する。
手動確認に逃がしてよいのは純粋な画面操作だけ(判断はコア関数として自動テスト=基礎3)。
入力様式が未定義で作れないものは「確定待ち」と明記(基礎7。穴ではなく上流の宿題)。
- 要求仕様書の「やらないこと」はテストしない。
【出力】
- テスト設計仕様書を .docx で出力する。
- テストコード(.py。pytest・@id/@verify付き・フィクスチャ生成を含む)は別ファイルで添える。
tests/ に置く想定で、ファイル名は test_*.py。
- トレーサビリティマトリクス(.xlsx)を添える。列:要求ID/階層/要求の内容/設計ID(関数)/
テストID(観点)/検証レベル(単体・結合・手動)。多対多なので表の行で結ぶ。
【構成】
1. テストの狙い
2. テスト観点の一覧(表:テストID/観点/入力/期待する出力/これで分かること/検証ID(REQ)/種類)
3. 重点的に狙う境目
4. テスト用入力データ(フィクスチャ)の作り方
5. テストコード(pytest・@id/@verify付き)
6. トレーサビリティマトリクス(要求ID×設計ID×テストID。自動/手動確認/確定待ちを区別)
7. テストしないこと設計の基礎(設計プロンプトと同時に渡す)
# 設計の基礎(このプロジェクトの共通ルール)
設計・テスト設計・実装の全フェーズで守る、共通の原則。
各フェーズのプロンプトは、このファイルを一緒に渡して「設計の基礎に従う」として参照する。
## 1. 設計とテストは独立に作る(独立性)
- 各フェーズは、前フェーズの成果物(要求仕様書・設計仕様書などの文書)だけを唯一の入力とする。
会話の履歴・記憶を根拠にしない。穴・確定待ち・矛盾の判断も、渡された文書に書いてあるか・いないか
だけで決める。「前に会話でこう言った」を持ち出すと、確定済みの事項を曖昧と誤判定したり、
文書に無い穴を作り出したりする(幻の穴)。だから各フェーズは独立したチャットで行う。
- 設計仕様書には実装の中身(コード)を書かない。書くのは日本語の手順と、各関数の取り決めだけ。
- テストは、実コードを見ず・走らせず、設計の取り決めと要求仕様書の期待値から書く。
- テストとコードは、実装フェーズで初めて出会う(pytest 実行)。これで「動く」でなく「正しい」を確かめる。
- テストの期待値は、要求仕様書の計算例(人間が確認済みの正解)に紐づける。コードから逆算しない。
## 2. 取り決め(関数の入口と出口の約束)は物理表現まで定義する
各関数の取り決め(名前・受け取るもの・返すもの)には、テスト設計者がこれだけでテストを書ける粒度まで:
- 関数名・引数(名前と型)・戻り値
- 戻り値や受け渡すデータの物理表現:dataclass か dict か、フィールドの英語名と型
(例:LotResult は dataclass。属性 lot_no:str, mean:float, status:str)
- モジュール構成:ファイル名=import名(例:コアは core.py = import core)
- 値の決まり:日付の入力形式、丸めの桁、状態を表す文字列の値("採用"/"除外" など)
取り決めが曖昧だと、テストを書く人と実装する人が別々の名前・戻り値を想定して噛み合わない。
中身(アルゴリズム)は書かず、表面の取り決め(何を受け取り何を返すか)は具体的に共有する。
## 3. UIに判断を置かない
- コア(計算・判定)とUI(画面)は役割を分ける。UIはコアを呼ぶだけ。
- 判断(中断する/警告する/弾く/続行する など)は、画面のボタンやイベントに紐づくものでも、
コア側の関数に切り出す。UIはそれを呼んで結果を表示するだけ。
- UIに残してよいのは、純粋な画面操作(要素の配置・表示・入力の受け渡し)だけ。
- 守らないと、判断がUIに埋もれて自動テストできず、「画面操作だから手動確認」で逃げてしまう。
## 4. ファイルは増やしすぎない
- 原則 models(データ構造)・core(読み込み・計算・判定・出力の全関数)・ui(画面)の3つに収める。
- 設定値(しきい値など)が多ければ config を足してよい。
- 「関心を関数で分ける」ことと「ファイルを分ける」ことは別もの。reader/validator/writer のように
機能ごとにファイルを増やさない。役割ごとの関数はコメントで区切って同じ core に並べる。
## 5. 正常系以外を必ず定義する
正常に動く場合だけでなく、次の5つを定義する(抜けると実装もテストも決められない):
- 失敗・例外の経路:開けない・壊れている・権限がない・想定外の構造のとき、例外を投げるのか、
エラーを表す戻り値(status 等)に畳むのか。技術的な失敗(I/O・破損・ロック)も。
- 値の境界・特殊値:空・欠損・非数値・エラー値・ゼロ・極端な値のとき、どう扱うか。
- 状態とデータの整合:ある状態(不整合・除外など)のとき、保持するデータの中身は何か。
- 件数・重複の境界:0件・1件・重複のとき、どうふるまうか。キーが衝突したら誰がどう止めるか。
- 結果に影響する技術前提:ライブラリの動作モードで結果が変わる箇所は前提を明記
(例:Excel を数式の文字列で読むのか、計算済みの値で読むのか)。
## 6. 検証できる形になっているか
- 各要求を検証する情報が、関数の戻り値やデータ構造に乗っているか。乗っていなければ、
実装が何を入れても通ってしまう(=検証不能)。例:「不整合のセル番地を報告する」要求なのに、
抽出関数が値しか返さず番地を持たないなら、その要求はどの戻り値からも確かめられない。
- 本文と、データ構造・対応表が、互いに矛盾していないか。
## 7. 確定待ち(勝手に埋めない・リスクで仕分ける)
- 決められない点は、勝手に仮定で埋めず「確定待ち」として、何を決めれば埋まるかと一緒に明記する。
- それが本来は要求仕様書にあるべき穴(様式・ふるまい)なら、要求側の穴である旨を明記する。
- 各確定待ちに、リスクの大きさを添える。リスクは「影響度 × 発生頻度」で見積もる。
・影響度:大=間違った結果が正しく見えるまま出る(静かなデータ破損)/中=目に見えて止まる
(気づける失敗)/小=見た目が変わる程度。
・発生頻度:正しく運用されたデータで、どれくらい起きるか(よく/たまに/ほぼ起きない)。
頻度は要求の文言だけで決めず、添付された実データ(入力サンプル・完成ファイル)を実際に見て
見積もる。実データで起こりうるか確かめてから強度を決める(例:要求に「表記ゆれを正規化」とあっても、
添付サンプルにゆれが無ければ頻度は「ほぼ起きない」)。実データを見れば消えるリスクを文言だけで
過大計上しない。確かめる実データが無ければ【未検証】と明記する。
- リスク大→要求仕様書に戻って定義/リスク中→既定で進め次バージョンで検討と記録/
リスク小→既定のままでよい(要求に戻さない)。最終判断は人間。
- 全部を要求仕様書に戻さない。リスクと労力で線を引く。静かなデータ破損(影響度大)だけは、
頻度が低くても軽視しない。
## 8. 要求とのつながり
- 要求仕様書は仕上げ確認を通った確定版とみなす。要求で決まっていることは再確認しない。
- 要求IDごとに、それを実現する関数/確かめるテストを割り当て、全IDに担当があることを確認する。
## 9. ID体系(要求・設計・テストをつなぐ)
- 要求ID(REQ-x.x):要求仕様書が幹。唯一の採番元。大・中・小の階層。
- 設計ID(DES-):関数を一意に指す。モジュール大・関数中(core→DES-C01…/ui→DES-U01…/models→DES-M01…)。
- テストID(V-):観点を主軸に振る(V-01…)。種類(単体/結合/手動)は観点の属性(列)にし、分類軸にしない
(1観点が単体と手動にまたがるため)。
- 3者は多対多(1関数が複数要求/1要求に複数関数)。番号一致では表せず、トレーサビリティマトリクスで結ぶ。
- コードに刻む:実装の関数は「@id: DES-Cxx + @spec: REQ-x.x(一言)」、テストは「@id: V-xx + @verify: REQ-x.x(一言)」。
タグは関数の本体の中の「# コメント行」に書く(docstring の中には書かない。整合チェックが拾えず未検証と誤判定される)。1行に1つのIDだけ(複数は行を分ける)。
## 10. 変更するとき(版を上げる)── 既存を壊さず差分を積む
確定版ができたあと、7の「次バージョンで検討」とした宿題や、新しい要望を取り込むときの約束。
初版を新規に作るときは、この章は該当しない(版を上げる元がないため)。
- 版には2段ある。**メイン版**(フォルダ単位)と**枝番**(仕様書単位の軽微な改訂)。
・メイン版(第1版・第2版…= v1/・v2/ フォルダ):新しい要求・新機能を取り込む変更フローのとき、フォルダごと一つ上げる。大きな版はフォルダで管理し、最新版フォルダ(vN の N が最大)が常に最新。
・枝番(第2.1版・第2.2版…):新機能を伴わない軽微な改訂——現物への追従や、乖離回収(コードや現物に対して仕様の記述が古くなったのを直す)——のとき、直した仕様書だけ、その仕様書の中の版表記を枝番で一つ上げる。フォルダは増やさない(v2.1/ というフォルダは作らず、v2/ の中の docx の版表記だけが進む)。
・枝番は仕様書ごとに独立して進む。要求だけ直したなら要求仕様書 第2.1版、設計・テストは据え置き。全部を同じ枝番へ無理に揃えない(中身の変わらない仕様書を番号だけ上げる空改訂はしない)。
- 設計・テストの仕様書には、対応する要求仕様書の版を併記する(どの要求版に紐づくかを残す。枝番が仕様書ごとにばらついても、この併記で紐づけを追える)。変更後の要求仕様書の最新(メイン版+枝番)を、新たな確定版として扱う(8の「確定版とみなす」は、その時点の最新を指す)。
- 既存のIDは振り直さない(REQ・DES・V すべて)。番号は資産。変えると過去のトレーサビリティが切れる。
- 足すIDは、既存の続き番号で起こす。
- やめるIDは、行を消さず「廃止」と印を付け、理由を一言添える(過去のロットや記録から辿れるように)。
- 意味が変わるIDは、原則 旧IDを「廃止」にし、新IDを起こす。
単なる文言の整理(意味は同じ)は、同一IDのまま直す。
- 既存の関数の契約(名前・引数・戻り値)は、変更対象に挙がらないかぎり変えない。既存の通っている
テストが、そのまま通り続けることを前提に置く(リグレッションを起こさない)。契約を変えるしか
ないときは、勝手に変えず、なぜ必要か・どの既存テストに波及するかを報告して止まる。
- 変更は「外側/内側」で進め方を分ける(リスクで仕分け=7の影響度と同じ考え)。
・外側=表示・レイアウト・グラフの形など、間違っても目で気づけるもの。対応箇所を直接直し、
結果を上流の仕様書へ一行追記する(差分の逆輸入)。設計・テストは作り直さない。
・内側=計算・判定・入力定義など、間違っても静かに通ってしまうもの。要求仕様書から見直し、
設計・テストの仕様書も版を上げて改訂する。
- 各フェーズの変更は、最初に差分サマリーを出す:追加したID/廃止したID(理由)/
記述だけ直したID/波及した既存の範囲。波及しない箇所は触らない(最小構成)。
- 実装と仕様が食い違ったときの戻し方(乖離回収)。内側の変更フローでは、実装後のテスト実行の締めに、コードと仕様の
乖離チェックを一度行う(テスト実行チャットの責務)。食い違いが見つかったら、勝手にどちらへも寄せず、差分を出して
報告する。直す向きは人が決める:仕様(多くは要求)が現物より古いなら、ずれた仕様だけを枝番でマイナー改訂して
実物に合わせる(メイン版=フォルダは上げない)。コードが仕様を外しているなら、実装側を直す。差分の検出
(コードを見られる側=Claude Code)と、仕様の修正(仕様を持つ側=Web Claude)は、別の手に分ける(作った本人が
自分の食い違いを判定しない=独立性)。軽い変更で乖離チェックを省いたときは、版を閉じる前に、人が一度、
コードと要求仕様のずれを能動的に確かめる。何を読み取るべきかを、トレーサビリティマトリクスで対応づける
テストを作るときは、読み取るべき項目の一つひとつに、対応するテストがあるかを確かめます。この対応を管理する表が、トレーサビリティマトリクスです。要求(何を読み取るべきか)に、確かめるテストが漏れなく結びついているかを追うための表です。
今回のマトリクスには、要求の内容・対応する設計・テストの観点・検証レベルが並びます。一部を抜き出すと、次のようになっています。
| 読み取るべき項目(要求) | 検証レベル |
|---|---|
| フォルダ内のPDFを一覧化する | 単体・手動 |
| 測定4回分の値を読み取る | 単体・結合・実機 |
| 自信の低いセルを赤く表示する | 単体・手動 |
| 確認後の結果を31列のExcelにまとめる | 単体・結合 |
注目したいのは、右端の検証レベルです。項目によって、単体・結合だけで済むものと、実機や手動が必要なものに分かれています。すべてを同じやり方で確かめられるわけではないということが、この表から見えてきます。マトリクスの全体は、下のボタンから読めます。
自動で確かめられない部分は、人が確かめる観点として一覧にする
テストを走らせると、機械的に正解が決まるところは、自動で確かめられました。受け取ったデータの形、製造日順の並べ替え、Excelの列の並びなど、正解が一つに決まるものは、単体テストで通りました。
ところが、自動では確かめられない部分が出てきます。最大のものが、生成AIの読み取りの精度です。読み取った値が正しいかどうかを、機械的に判定する仕組み(オラクル)が作れないのです。別のAIに正誤を判定させても、そのAIも同じように間違えるため、正しさの保証にはなりません。だから、読み取りの精度は、人が完成イメージと突き合わせて確かめるしかありません。
そこで、自動テストにできない部分を一覧にして、人がどの観点で確かめるかを、あらかじめ決めておきます。今回、人が確かめる観点として残したのは、次のものです。
- 読み取りの精度:
サンプルの読み取り結果が、正解(完成イメージ)と合っているか。機械的な正誤判定ができないため、人が突き合わせる。 - Ollamaとの連携:
画像を渡したときに、想定した形で結果が返ってくるか。外部の道具とのやり取りなので、実際に動かして確かめる。 - 画面の表示:
1記録票=1行で全項目が表に並び、自信の低いセルが赤く表示されるか。 - 画面の編集:
セルを直すことができ、直したら赤が外れるか。 - 保存:
保存先を選んで、Excelに出力できるか。 - 決めきれていない点:
自信度の測り方や、赤くするしきい値。実際に動かしながら調整して決める。
これらは、単体テストが通ったあとも残る、人が確かめるべき宿題です。一覧にして残しておくことで、どこを見ればよいかが後から分かります。自動テストが通っても、この観点を人が確かめなければ、動くアプリではあっても、正しいアプリにはならない。確かめられるところと確かめられないところを分け、確かめられない部分を宿題として残す。これが、今回のテストの締めになります。
テストの観点をまとめたテスト設計仕様書は、下のボタンから読めます。
本アプリの展望:改善と高性能なサーバーを1台に集約する
今回のツールは、手元のパソコン1台で動かしました。ここから、職場全体の業務効率化につなげるには、どう広げればよいか。まず、今回のツールに残る限界を押さえたうえで、その先の進め方を書いておきます。
手書きの読み取りには、誤りが残る
今回のツールの限界は、手書きの読み取りにあります。印字された文字と違い、手書きは読み取りミスが起きます。たとえば、小数点(.)とハイフン(-)のような似た記号を取り違えると、数値としてうまく出てこないことがあります。だからこそ、確信度の表示と人の確認が欠かせません。また、この精度をもっと上げたい、となると、より高性能なモデルを使いたくなります。ただし、高性能なモデルほど、動かすのに強いGPU、高性能なPCが要ります。
全員のPCにGPUを積むのではなく、良いサーバーを1台作る
高性能なモデルを動かすには強いGPUが要りますが、社員全員のパソコンにGPUを積むのは、費用の面でも管理の面でも現実的ではありません。一人ひとりの手元を強化していくのは、無理があります。
強いGPUを積んだサーバーを、社内に1台だけ用意する。そして、各自の手元のパソコンからは、そのサーバーに処理を送ります。手元のパソコンは軽いままで、重い読み取りは1台のサーバーが引き受けます。


この形にすると、良いところがいくつも重なります。1台に集約すれば、高性能なモデルを全員で共有できる。手元のパソコンにGPUは要らず、費用も管理もサーバー1台に集まります。そして、クラウドに出すのではなく社内のサーバーに集約するだけなので、記録は社外に出ず、機密が保たれます。どう実行するかというと、読み取り部分の機能だけをサーバーに集約してUIは各自のPCで表示できる設計をします(属にいう、クライアントサーバー方式)。
常時稼働しない読み取り機能を高性能なサーバーを引き受けて、管理する。職場全体の業務効率化、システム化を進めていく現実的なやり方です。
まとめ
紙のまま溜まっていく製造記録を、あとから使える形にする。この課題を、手元のパソコンで動くローカルの生成AIを使い、要求から実機まで通して解いてみました。
- 紙の記録は、検索も、まとめて見返すこともできないため、あとから使える形にしたかった
- 記録は機密なので、クラウドに出さず、手元のパソコンだけで完結させた
- 何を読み取り何を返すかは、問診形式のプロンプトで要求仕様書にまとめた
- 読み取りをコア、画面をUIに分け、Ollamaの上で画像を読めるモデルを動かした
- 実装はClaude Codeと進め、環境構築も作法もCLAUDE.mdに従わせた
- 正しさは、機械的に確かめられる範囲を自動テストで、そうでない読み取り精度は人が確かめる観点として残した
手元1台で完結させた仕組みは、高性能なサーバー1台に集約することで、職場全体の効率化へと広げていけます。小さく作って確かめ、確かな土台の上に広げる。その進め方の見本になれば幸いです。
※注意:この記事で扱ったデータ・品名・測定値は、すべて架空のものです。実在の企業・製品とは関係ありません。









コメント