公開・本番移行学習記事全11節Build
配置サンドボックスにアプリとデータを配置し、確認コマンドで確かめる
この記事で身につくこと配置対象と版を明確にし、手順と実行結果を記録する理由と、「配置できた」と「使える」が別であることを説明できる。
記事内目次(23項目)
この記事の会社・人物・データはすべて架空の設定です。実在する会社や案件とは関係ありません。この記事の「配置」は、教材演習用のローカルフォルダ(配置サンドボックス)への配置であり、実際の外部サービス(クラウド等)への配置ではありません。本文のコードは
examples/11-02-deploy-record/の正本と同じもので、実行結果は2026-09-20にローカル環境で実際に実行して記録したものです(第6〜7節、実行記録は第9節)。第5.4節の指示文と第6.1節の初稿は説明用の例で、実際のAI出力を観測したものではありません。
この記事は何の話か。08-01で作った承認可否の判定関数と、10-02で移行できたデータを、前工程の成果物のファイルそのものとしてローカルの「配置サンドボックス」にコピーし、確認コマンドで健全性を確認する話です。
なぜ必要か。配置の対象・版・手順を明確にしておかないと、「何を、どの版まで配置したか」が分からなくなり、問題が起きたときに切戻し(11-04で扱う)もできません。また、「前工程の成果物を配置した」と言いながら、実際には配置スクリプトの中に別の写しを埋め込んでいると、前工程で直した内容が配置に反映されず、記録と実物が食い違います。
この記事を読むとできるようになること。
- 配置対象と版を明確にし、手順と実行結果を記録する理由を説明できる
- 前工程の成果物を実ファイルとして配置し、配置元と配置先が同一であることを確かめて実行記録を残せる
- 手作業の配置と自動化した配置を、再現性・手間・誤操作の危険から比較できる
読む順路。この記事は3つの深さで読めます。全部を順に読む必要はありません。
- 基本だけ理解する:第1節→第3節(「配置できた」と「使える」は別)→第4節(判断すること)→第5.1節(配置対象・版・配置元)→第6.2節の実行記録の表→第9節。コードを読まなくても、「何を、どこから、どこへ、どの版で」を記録する形が分かります。
- 作って確かめる:上に加えて第5.2〜5.3節(配置処理と確認コマンド)→第5.4節(AIに頼む)→第6節(初稿の不備と、修正後の実行結果)→第7節。
- 設計判断を深める:上に加えて第8節(手作業と自動化の比較、適用限界)。
1. 今回の業務課題と完成するもの
この記事でやることは、08-01の承認可否の判定関数と、10-02で移行できた3件のデータを、ローカルの配置サンドボックスに配置する手順を作り、実際に配置して確認コマンド(健全性確認)を実行し、実行記録に残すことです。配置するのは、前工程のフォルダにある実際のファイル(examples/08-01-minimal-example/approval.js と、10-02を実行して生成される examples/10-02-migration-plan/migrated_requests.json)です。
11-01では配置前のチェックを行いましたが、実際に配置する手順と、配置できたことの確認方法はまだ扱っていませんでした。この記事では、それを扱います。
この記事を読み終えると、次のものが手元にできます。
- 配置・確認コマンドコード(
examples/11-02-deploy-record/) - 配置手順・実行記録(対象、版、手順、確認方法、期待結果、実行結果、実行者、日時)と、配置記録(
deploy_target/MANIFEST.json:配置元のパスと内容の指紋)
2. 前提知識と読む順路
この記事で使う言葉を先に説明します。
配置サンドボックス
一言でいうと、実際の外部サービスではなく、手元のパソコンの中に作った、配置を試すための場所です。この記事では、フォルダの中に「配置先」を再現します。
版
一言でいうと、配置するアプリのどの時点のものかを表す名前です。この記事では「v0.1.0-sandbox」という名前を使います。
確認コマンド
一言でいうと、配置した後に、正しく配置できているかを確かめるための操作です。この記事では、配置したアプリの関数を実際に呼び出し、配置したファイルが配置元と同一かを確かめます。
内容の指紋(ハッシュ)
一言でいうと、ファイルの中身から計算した短い文字列で、中身が1文字でも違えば値が変わるものです。
たとえば、配置元の approval.js と配置先の approval.js の指紋が同じなら、中身が同一だと言えます。
これがないと、「コピーしたつもり」と「本当に同じもの」を区別できません。
システム開発では、これをハッシュ(hash。この記事ではSHA-256)と呼び、配置や移行で「同じものが届いたか」を確かめるのに使います。
これがないと、「配置できた」と思っても、実際には正しく動くかどうか、前工程で作ったものと同じかどうかが分からず、「使える」状態になっているかを確認できません。
読む順路:公開前チェックは11-01、変更履歴は06-03、移行計画は10-02、接続先の確認は06-02が該当します。この記事の実行記録は、11-03(段階的に利用を始める)、11-04(切戻しと初期安定を確認する)で使います。
3. 理解する:「配置できた」と「使える」は別
3.1 配置対象・版・手順を明確にする理由
何を(対象)、どの時点のものを(版)、どこから(配置元)、どうやって配置したか(手順)が分からないと、後で問題が起きたときに、何を切戻せばよいかが分かりません(11-04で扱います)。
3.2 「前工程の成果物を配置する」とは、そのファイルを使うこと
結論から言うと、配置とは「前工程が作った実物を、動く場所へ運ぶ」ことで、配置スクリプトの中に同じ内容を書き写すことではありません。
みらい業務サービスの例で言うと、08-01で判定関数に不備が見つかって直したとします。配置スクリプトが08-01のファイルをコピーしていれば、次の配置で直った版が届きます。配置スクリプトに関数の中身を書き写していれば、08-01を直しても配置には古い中身が届き、「配置した版」と「前工程の成果物」が別物になります。しかも配置記録には「08-01の関数を配置した」と書いてあるので、食い違いに気づけません。
この記事の初版は、まさにこの「書き写し」になっていました(第6.1節)。
3.3 よくある誤解
「ファイルをコピーできれば配置完了」。ファイルが配置先に存在することと、そのアプリが正しく動くことは別です。この記事では、配置後に確認コマンドを実行し、期待どおりに動くかを確認します(第5.3節・第6節)。
「同じ内容なら、コピーでも書き写しでも同じ」。今日は同じでも、前工程が更新されたときに追随するかどうかが違います(第3.2節)。
「配置サンドボックスでの確認は、本番でも通用する」。配置サンドボックスは、あくまでローカルでの手順の確認です。実際の外部サービスへの配置では、接続先やネットワークなど、この記事では確認していない要素が関わります(第8.2節)。
4. 判断すること
配置手順を作るときに人が判断することは、次の5つです。
| 判断すること | なぜ判断が必要か | 仮置きしてよいか | 間違えた場合の影響 |
|---|---|---|---|
| 何を配置するか(対象)と、その配置元はどのファイルか | 配置元が「前工程の正本」でなければ、配置は前工程とつながらない(第3.2節) | 不可。配置元は前工程の実ファイルを指す | 前工程で直した内容が配置に反映されない。記録と実物が食い違う |
| 版をどう付けるか | 切戻し(11-04)で「どの版に戻すか」を言うため | 可(この記事は v0.1.0-sandbox。正式な付け方は06-03) | 何を戻せばよいか分からない |
| 配置元がそろっていないとき、止めるか、代わりを作るか | 10-02の移行データは10-02を実行しないと存在しない。無いときに配置スクリプトが勝手に作ると、「前工程の成果物」ではなくなる | 不可。無ければ止めて、前工程を実行するよう案内する | 配置スクリプトが作った別物のデータが「移行データ」として配置される |
| 確認コマンドで何を確かめるか(動くか、同一か、件数、版) | 「動く」だけでは、前工程と同じものが届いたかは分からない | 可(この記事は動作1件・同一性2件・件数・版の5項目。運用に入れば12-01で増やす) | 古い版が配置されていても「一致」と出る |
| 実行した範囲と未検証の範囲をどう書き分けるか | サンドボックスでの成功を本番の保証と読ませない | 不可 | 「配置できた」が「本番で使える」と誤読される(10-04の判定区分の飛躍) |
勝手に決めてはいけないこと:実際の外部サービスに配置したかのように書きません。この記事はローカルの配置サンドボックスです。10-02で移行しなかったデータ(REQ-OLD-003、004)を、この記事で配置対象に含めません。配置元のファイルが無いときに、配置スクリプトが代わりのデータを作りません。
AIに任せる範囲:配置スクリプトと確認コマンドの下書き、実行して出力をそのまま返すこと、配置記録(MANIFEST)の形式の提案はAIに任せられます。任せてはいけないのは、配置元をどのファイルにするか、版の付け方、配置元が無いときの扱い、そして「配置スクリプトが前工程の実ファイルを本当に使っているか」の確認です。AIは「同じ内容を埋め込めば動く」形を書きがちです(第6節)。
5. 作って確かめる:配置手順を作り実行する
5.1 配置対象・版・配置元
| 項目 | 内容 |
|---|---|
| 配置対象 | 08-01の承認可否の判定関数(アプリ)、10-02で移行できた3件のデータ |
| 配置元(アプリ) | examples/08-01-minimal-example/approval.js(08-01の正本) |
| 配置元(移行データ) | examples/10-02-migration-plan/migrated_requests.json(10-02の run.js を実行すると生成される。実行前は存在しない) |
| 版 | v0.1.0-sandbox |
| 配置先 | ローカルの配置サンドボックス(examples/11-02-deploy-record/deploy_target/) |
| 配置記録 | deploy_target/MANIFEST.json(版、配置日時、配置元の相対パス、配置元の内容の指紋) |
5.2 配置処理
配置元がそろっているかを確かめてから、実ファイルをコピーし、配置記録を書きます(examples/11-02-deploy-record/deploy.js)。
// 教材演習用:ローカルの「配置サンドボックス」に、前工程の成果物を実際のファイルとして配置し、
// 確認コマンドで健全性を確認する。実際の外部サービスへの配置ではない。
// 配置するもの:
// - アプリ:08-01 の正本 examples/08-01-minimal-example/approval.js(そのファイルをコピーする)
// - 移行データ:10-02 を実行して生成された examples/10-02-migration-plan/migrated_requests.json(そのファイルをコピーする)
// Node.js標準機能(node:fs、node:path、node:crypto)のみを使用する。
const fs = require("node:fs");
const path = require("node:path");
const crypto = require("node:crypto");
const SANDBOX_DIR = path.join(__dirname, "deploy_target");
const APP_DIR = path.join(SANDBOX_DIR, "app");
const DATA_DIR = path.join(SANDBOX_DIR, "data");
const VERSION = "v0.1.0-sandbox";
// 前工程の成果物(配置元)。文字列を埋め込むのではなく、実在するファイルを指す。
const APP_SOURCE_FILE = path.join(__dirname, "..", "08-01-minimal-example", "approval.js");
const DATA_SOURCE_FILE = path.join(__dirname, "..", "10-02-migration-plan", "migrated_requests.json");
function sha256(file) {
return crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
}
// 配置元がそろっているかを先に確かめる。10-02 の出力が無ければ、10-02 を先に実行するよう案内して止める。
function checkSources() {
const missing = [];
if (!fs.existsSync(APP_SOURCE_FILE)) missing.push(`08-01 の正本が見つかりません: ${path.relative(__dirname, APP_SOURCE_FILE)}`);
if (!fs.existsSync(DATA_SOURCE_FILE)) missing.push(`10-02 の移行データが見つかりません: ${path.relative(__dirname, DATA_SOURCE_FILE)}(先に examples/10-02-migration-plan で node run.js を実行してください)`);
return missing;
}
function deploy() {
fs.rmSync(SANDBOX_DIR, { recursive: true, force: true });
fs.mkdirSync(APP_DIR, { recursive: true });
fs.mkdirSync(DATA_DIR, { recursive: true });
fs.copyFileSync(APP_SOURCE_FILE, path.join(APP_DIR, "approval.js"));
fs.copyFileSync(DATA_SOURCE_FILE, path.join(DATA_DIR, "requests.json"));
fs.writeFileSync(path.join(SANDBOX_DIR, "VERSION"), VERSION + "\n");
// 何をどこから配置したかを記録する(配置元の相対パスと内容の指紋)
const manifest = {
version: VERSION,
deployedAt: new Date().toISOString(),
files: [
{ target: "app/approval.js", source: path.relative(__dirname, APP_SOURCE_FILE), sha256: sha256(APP_SOURCE_FILE) },
{ target: "data/requests.json", source: path.relative(__dirname, DATA_SOURCE_FILE), sha256: sha256(DATA_SOURCE_FILE) },
],
};
fs.writeFileSync(path.join(SANDBOX_DIR, "MANIFEST.json"), JSON.stringify(manifest, null, 2));
return manifest;
}
function healthCheck() {
const results = [];
// 確認1:配置したアプリ(関数)が期待どおり動くか
delete require.cache[require.resolve(path.join(APP_DIR, "approval.js"))];
const { canApprove } = require(path.join(APP_DIR, "approval.js"));
const actual = canApprove("提出済み", true, false);
results.push({ check: "アプリの健全性(canApprove)", expected: true, actual, ok: actual === true });
// 確認2:配置したファイルが配置元と同一か(内容の指紋の一致)
const appSame = sha256(path.join(APP_DIR, "approval.js")) === sha256(APP_SOURCE_FILE);
results.push({ check: "アプリが08-01の正本と同一(sha256)", expected: true, actual: appSame, ok: appSame });
const dataSame = sha256(path.join(DATA_DIR, "requests.json")) === sha256(DATA_SOURCE_FILE);
results.push({ check: "移行データが10-02の出力と同一(sha256)", expected: true, actual: dataSame, ok: dataSame });
// 確認3:移行データが配置されているか(件数)
const data = JSON.parse(fs.readFileSync(path.join(DATA_DIR, "requests.json"), "utf8"));
results.push({ check: "移行データの件数", expected: 3, actual: data.length, ok: data.length === 3 });
// 確認4:版が記録されているか
const version = fs.readFileSync(path.join(SANDBOX_DIR, "VERSION"), "utf8").trim();
results.push({ check: "版の記録", expected: VERSION, actual: version, ok: version === VERSION });
return results;
}
module.exports = { deploy, healthCheck, checkSources, SANDBOX_DIR, VERSION, APP_SOURCE_FILE, DATA_SOURCE_FILE };
「入力→判断・処理→出力→失敗時」の対応:
| 段階 | 内容 |
|---|---|
| 入力 | 配置元の2ファイル(08-01の正本、10-02の出力)、版の名前 |
| 判断・処理 | 配置元がそろっているか確かめる。そろっていれば配置先を作り直し、2ファイルをコピーし、版と配置記録を書く |
| 出力 | deploy_target/(app、data、VERSION、MANIFEST.json) |
| 失敗時 | 配置元が無ければ配置を行わず、何が無いか・何を先に実行するかを表示して終了コード1で止まる |
5.3 確認コマンド(健全性確認)と実行コード
確認コマンドは、配置後に5項目を確かめます。動くか(確認1)、配置先が配置元と同一か(確認2、2ファイル)、件数(確認3)、版(確認4)です。実行コードです(examples/11-02-deploy-record/run.js)。
// 教材演習用:配置サンドボックスへの配置と、確認コマンド(健全性確認)を実行する。
// 先に examples/10-02-migration-plan で node run.js を実行し、移行データ(migrated_requests.json)を作っておく。
const path = require("node:path");
const { deploy, healthCheck, checkSources, SANDBOX_DIR, VERSION, APP_SOURCE_FILE, DATA_SOURCE_FILE } = require("./deploy.js");
console.log(`配置対象: ローカル配置サンドボックス(${path.relative(process.cwd(), SANDBOX_DIR) || "."})`);
console.log(`版: ${VERSION}`);
console.log(`配置元(アプリ): ${path.relative(__dirname, APP_SOURCE_FILE)}`);
console.log(`配置元(移行データ): ${path.relative(__dirname, DATA_SOURCE_FILE)}`);
console.log("");
const missing = checkSources();
if (missing.length > 0) {
console.log("配置元がそろっていないため、配置を行いません:");
for (const m of missing) console.log(` - ${m}`);
process.exit(1);
}
const manifest = deploy();
console.log("配置手順を実行しました(アプリのコピー、移行データのコピー、版の記録、配置記録の作成)。");
for (const f of manifest.files) console.log(` ${f.source} → deploy_target/${f.target}(sha256: ${f.sha256.slice(0, 12)}…)`);
console.log("");
console.log("確認コマンド(健全性確認)の実行結果:");
const results = healthCheck();
for (const r of results) {
console.log(` ${r.check}: 期待結果=${JSON.stringify(r.expected)} 実際の結果=${JSON.stringify(r.actual)} 判定=${r.ok ? "一致" : "不一致"}`);
}
const allOk = results.every((r) => r.ok);
console.log("");
console.log(allOk ? "すべての確認項目が一致しました。" : "一致しない項目があります。");
process.exit(allOk ? 0 : 1);
5.4 AIに配置スクリプトを頼む
渡す情報と渡さない情報を先に決めます。
| 渡す情報 | 内容 | 渡さない情報と理由 |
|---|---|---|
| 配置対象と配置元 | 08-01の正本のパス、10-02の出力のパス(実行しないと存在しないこと) | 配置元ファイルの中身(渡すとAIが中身を埋め込む。パスだけを渡す) |
| 版と配置先 | v0.1.0-sandbox、このフォルダ直下の deploy_target/ | 実際の外部サービスの接続情報(存在しない。架空の題材) |
| 確認項目 | 動作、配置元との同一性(指紋)、件数、版 | — |
| 失敗時の扱い | 配置元が無ければ配置せず止める。代わりを作らない | — |
指示文は次のとおりです。これは説明のために書いた例で、実際にAIへ送信した記録ではありません。
ローカルの配置サンドボックス(このフォルダ直下の deploy_target/)へ、前工程の成果物を配置するスクリプトを JavaScript(Node.js 標準機能のみ)で実装してください。
配置元(実在するファイルをコピーしてください。中身をスクリプトに書き写さないでください):
- アプリ:../08-01-minimal-example/approval.js
- 移行データ:../10-02-migration-plan/migrated_requests.json(10-02 を実行すると生成される。無い場合は配置せず、先に 10-02 を実行するよう案内して終了コード 1 で止めてください)
版:v0.1.0-sandbox を deploy_target/VERSION に書く
配置記録:deploy_target/MANIFEST.json に、版・配置日時・各ファイルの配置元(相対パス)・内容の指紋(sha256)を書く
確認コマンド(配置後に実行):
- 配置した approval.js の canApprove("提出済み", true, false) が true
- 配置した2ファイルの sha256 が配置元と一致する
- 移行データが3件
- VERSION が v0.1.0-sandbox
返し方:
- deploy.js と run.js を返し、run.js の実行出力をそのまま貼ってください。
してはいけないこと:
- 配置元が無いときに、代わりのデータを作らないでください。
- 外部サービスへの接続を書かないでください。
6. 初稿・失敗例・修正
6.1 説明用の初稿(AIの初稿という設定)
第5.4節の指示に対して、次のような初稿が返ってきた、という設定にします(実際のAI出力を観測したものではなく、説明用の例です)。この初稿は、この記事の初版(Phase 5B-2B より前)に載せていたコードそのものです。
// 初稿(説明用。この記事の初版の deploy.js より抜粋)
// 配置対象:08-01で作成した承認可否の判定関数と同じもの(配置するアプリの版)。
const APP_SOURCE = `// 依頼の状態と操作者の役割を入力に、承認可否を返す最小の関数(08-01と同じもの。配置サンドボックス用のコピー)
function canApprove(state, isAssignedApprover, isSelf) {
if (state !== "提出済み") return false;
if (!isAssignedApprover) return false;
if (isSelf) return false;
return true;
}
module.exports = { canApprove };
`;
// 移行データ:10-02で移行できた3件(REQ-OLD-001、002、005)と同じ内容。
const MIGRATED_DATA = [
{ id: "REQ-OLD-001", requester: "佐藤", title: "会議室の予約", content: "9/25 10時から", approver: "鈴木", state: "提出済み", submittedAt: "2026-01-05" },
// …(残り2件)
];
function deploy() {
fs.writeFileSync(path.join(APP_DIR, "approval.js"), APP_SOURCE);
fs.writeFileSync(path.join(DATA_DIR, "requests.json"), JSON.stringify(MIGRATED_DATA, null, 2));
}
- 「08-01と同じもの」「10-02と同じ内容」と注記しながら、08-01のファイルも10-02の出力も読んでいない。中身を文字列と配列として書き写している
- 確認コマンドは「動くか」「件数」「版」だけで、配置元と同一かは確かめていない
- 10-02を実行していなくても配置が成功する(配置元に依存していないため)
6.2 見つけ方と直し方
見るところは3つです。配置スクリプトの中に、配置元のパスを読む処理(readFileSync、copyFileSync)があるか。「同じもの」と注記された中身がリテラルで書かれていないか。配置元を消したり未実行にしたりしたときに、配置が止まるか。
| 問題点 | なぜ問題か | どう見つけるか | 誰が判断するか | どう直したか |
|---|---|---|---|---|
| 関数の中身と移行データを文字列・配列で埋め込んでいる | 08-01・10-02を直しても配置に反映されない。記録の「08-01の関数を配置」が実物と食い違う(第3.2節) | deploy.js に配置元のパスが1つも出てこない。「同じもの」という注記のそばにコードの本文がある | 配置を確認する人(架空:開発担当) | 配置元のパスを定数にし、copyFileSync で実ファイルをコピーする形にした |
| 配置元との同一性を確かめていない | コピーが古い版でも「一致」と出る | 確認コマンドの項目に「配置元と同一か」が無い | 開発担当 | sha256 を配置元・配置先の両方で計算して比べる確認2を足し、MANIFEST.json に配置元と指紋を記録した |
| 10-02未実行でも成功する | 「10-02の移行データを配置した」と言えない | 10-02の出力ファイルを消して実行しても成功するか試す | 開発担当 | checkSources() で配置元の存在を確かめ、無ければ案内して終了コード1で止める形にした(第6.3節の手順1) |
AIへの修正指示は次のとおりです(説明用の例)。
指摘:
1. 関数の中身と移行データを文字列・配列として埋め込まないでください。配置元のファイル(../08-01-minimal-example/approval.js、../10-02-migration-plan/migrated_requests.json)を copyFileSync でコピーしてください。
2. 確認コマンドに、配置先のファイルが配置元と同一であること(sha256 の一致)を追加し、配置元のパスと指紋を MANIFEST.json に記録してください。
3. 10-02 の出力が無いときは配置を行わず、先に 10-02 を実行するよう案内して終了コード 1 で止めてください。
変えないこと:
- 版(v0.1.0-sandbox)と配置先(deploy_target/)は変更しないでください。
- 外部サービスへの接続は追加しないでください。
6.3 修正後の実行結果(配置手順・実行記録)
examples/11-02-deploy-record/ で、次の順に実行した stdout と終了コードです(整形・省略なし。stderr への出力はありませんでした。MANIFEST.json の deployedAt は実行のたびに変わります)。
手順1:10-02を実行していない状態で配置を試みる(配置元が無いので止まる)。
$ node run.js
配置対象: ローカル配置サンドボックス(deploy_target)
版: v0.1.0-sandbox
配置元(アプリ): ../08-01-minimal-example/approval.js
配置元(移行データ): ../10-02-migration-plan/migrated_requests.json
配置元がそろっていないため、配置を行いません:
- 10-02 の移行データが見つかりません: ../10-02-migration-plan/migrated_requests.json(先に examples/10-02-migration-plan で node run.js を実行してください)
終了コード: 1
手順2:examples/10-02-migration-plan/ で node run.js を実行し、移行データを生成する(出力は10-02と同じ。読み込み5行、移行3件、移行しない2件。終了コード0。全文は第9節の実行記録)。
手順3:配置と健全性確認。
$ node run.js
配置対象: ローカル配置サンドボックス(deploy_target)
版: v0.1.0-sandbox
配置元(アプリ): ../08-01-minimal-example/approval.js
配置元(移行データ): ../10-02-migration-plan/migrated_requests.json
配置手順を実行しました(アプリのコピー、移行データのコピー、版の記録、配置記録の作成)。
../08-01-minimal-example/approval.js → deploy_target/app/approval.js(sha256: 6dc21fe173b6…)
../10-02-migration-plan/migrated_requests.json → deploy_target/data/requests.json(sha256: e1ec5e804e69…)
確認コマンド(健全性確認)の実行結果:
アプリの健全性(canApprove): 期待結果=true 実際の結果=true 判定=一致
アプリが08-01の正本と同一(sha256): 期待結果=true 実際の結果=true 判定=一致
移行データが10-02の出力と同一(sha256): 期待結果=true 実際の結果=true 判定=一致
移行データの件数: 期待結果=3 実際の結果=3 判定=一致
版の記録: 期待結果="v0.1.0-sandbox" 実際の結果="v0.1.0-sandbox" 判定=一致
すべての確認項目が一致しました。
終了コード: 0
手順4:配置記録の中身。
$ cat deploy_target/MANIFEST.json
{
"version": "v0.1.0-sandbox",
"deployedAt": "2026-09-20T14:32:22.652Z",
"files": [
{
"target": "app/approval.js",
"source": "../08-01-minimal-example/approval.js",
"sha256": "6dc21fe173b66aebb69e9ac2553ebdf123ba1db29ee9ee5bfc33705218156141"
},
{
"target": "data/requests.json",
"source": "../10-02-migration-plan/migrated_requests.json",
"sha256": "e1ec5e804e6987fd41024be7b0f03c54a2b6f448ce46c7ac8a4659c2cb3e40c0"
}
]
}
手順5:配置したファイルと配置元を diff で比べる(出力なし=同一。終了コード0。第9節の実行記録)。
| 対象 | 版 | 配置元 | 手順 | 確認方法 | 期待結果 | 実行結果 | 実行者 | 日時 |
|---|---|---|---|---|---|---|---|---|
| アプリ(canApprove) | v0.1.0-sandbox | examples/08-01-minimal-example/approval.js | copyFileSync でコピー | 動作1件、sha256一致、版 | 一致 | 一致(手順3) | Claude Code(演習) | 2026-09-20 |
| 移行データ3件 | 同上 | examples/10-02-migration-plan/migrated_requests.json(10-02実行後) | copyFileSync でコピー | sha256一致、件数3 | 一致 | 一致(手順3) | 同上 | 同上 |
7. 確認結果
実行環境:macOS 26.6.2、Node.js v24.18.0(node:fs・node:path・node:crypto のみ使用)、2026-09-20に実行。配置先はローカルの配置サンドボックスのみで、外部のサーバー・クラウドサービスには接続していません。stdout・stderr・終了コードをそのまま記録した実行記録は第9節の run_log.md にあります。
完了条件との照合:
| 完了条件 | 確認結果 |
|---|---|
| 配置した版が特定できる | 第5.1節・第6.3節に記載(v0.1.0-sandbox。VERSION と MANIFEST.json に記録) |
| 各手順に確認方法と期待結果がある | 第5.2〜5.3節・第6.3節の表に記載 |
| 実行済みと未検証が区別されている | 本節に記載 |
実行済み:ローカルの配置サンドボックスへの配置(前工程の実ファイルのコピー)、健全性確認5項目、配置元との diff、配置元が無い場合に止まること。
未検証:実際の外部サービス(クラウド等)への配置、複数の利用者からの同時アクセスに対する動作、配置先での実際の利用(11-03で演習)。第5.4節の指示文と第6.1節の初稿は説明用の例であり、実際にAIへ送信・観測した記録ではありません。この記事の本文はClaude Codeが作成したもので、業務担当者による内容確認は行っていません。
8. 設計を判断する
8.1 手作業の配置と自動化した配置を比較する
| 方法 | 内容 | 再現性 | 手間 | 誤操作の危険 |
|---|---|---|---|---|
| 手作業の配置 | ファイルを1つずつ手でコピーし、確認する | 低い(毎回手順が微妙に変わりうる) | 少ない(小規模なら) | 高い(コピー漏れ、確認忘れ、古い版のコピー) |
| 自動化した配置(この記事で採用) | スクリプト(deploy.js)で配置元から配置・確認・記録を行う | 高い(毎回同じ手順が実行され、配置元と指紋が記録に残る) | 準備に手間がかかる | 低い(スクリプトどおりに実行される。配置元が無ければ止まる) |
この記事の教材演習では、規模は小さいものの、再現性と誤操作の危険を優先し、自動化した配置(スクリプト)を採用しています。ただし、自動化しても「配置元が前工程の正本を指しているか」は人が確かめる必要があります(第6.2節)。
8.2 適用限界
この配置サンドボックスは、ローカルのフォルダにファイルをコピーするだけの単純なものです。実際の外部サービスへの配置では、接続設定、権限、ネットワークの状態など、この記事では扱っていない要素が関わります。実際の配置先が決まった段階で、あらためて確認する必要があります。
9. 持ち帰る成果物
| 成果物 | 空欄版 | 記入例 |
|---|---|---|
| 配置手順・実行記録ひな形(対象、版、手順、確認方法、期待結果、実行結果、実行者、日時) | templates/11-02-deploy-record_template.md | templates/11-02-deploy-record_example.md |
| 配置・確認コマンドコード一式 | examples/11-02-deploy-record/(deploy.js、run.js) | 同上 |
| 実行記録(stdout・stderr・終了コード、整形なし) | — | evidence_public/phase5b2b-2026-09-20/11-02/run_log.md |
自分の業務に使うときの手順は次のとおりです。
- 配置対象と版を明確にし、配置元を前工程の実ファイルで指す
- 配置手順を書き、確認コマンド(動作・同一性・件数・版)と期待結果を決める
- 実行できる範囲(配置サンドボックスなど)で実行し、配置記録(配置元と指紋)と実行記録に残す
- 実行しない項目(実際の外部サービスへの配置など)は未検証と明記する
10. 次工程への受渡し
次へ渡すもの:配置手順・実行記録、配置記録(MANIFEST.json)。
次工程での使われ方:11-03(段階的に利用を始める)では、この配置を前提に初期利用を演習します。11-04(切戻しと初期安定を確認する)では、この記事の配置対象・版・配置記録をもとに切戻し手順を作ります。
前工程へ戻る条件:健全性確認で不一致が見つかった場合は、配置手順そのものを見直します。配置元の同一性(sha256)が一致しない場合は、配置元(08-01・10-02)が更新されていないかを確認します。
11. 根拠と更新情報
- この記事の会社・人物・データはすべて架空の設定です。
- 配置するアプリは08-01の正本、移行データは10-02の出力に基づき、いずれもそのファイルをコピーしています。
- 第5.4節の指示文は、この記事のために書いた指示文の例であり、実際にAIへ送信した記録ではありません。第6.1節の初稿は説明用の例であり、実際のAI出力を観測した記録ではありません(内容はこの記事の初版のコードに基づきます)。
- 制作の来歴:本文はClaude Codeが作成しました。第5〜6節のコードは
examples/11-02-deploy-record/を正本とし、2026-09-20にmacOS 26.6.2・Node.js v24.18.0の環境で実際に実行して、stdout・stderr・終了コードをevidence_public/phase5b2b-2026-09-20/11-02/run_log.mdに記録しています。人(ユーザー)による実読・内容確認は未実施です。 - 2026-09-20(Phase 5B-2B):受入監査で「08-01のコードと10-02の移行データを『成果物として利用した』と説明しながら、実際は deploy.js に文字列リテラルとして埋め込んでいた」と指摘された。
deploy.jsを配置元の実ファイルをコピーする形に改め、配置元との同一性(sha256)の確認と配置記録(MANIFEST.json)を加え、配置元が無い場合は止める形にした。実行結果を再実行の実測に置き換えた。あわせて読む順路、第4節の判断項目、第5.4節「AIに配置スクリプトを頼む」、第6節の初稿→レビュー→修正、CHECKLIST、記事間の参照を追加した。 - 未確認事項:実際の外部サービスへの配置、複数の利用者からの同時アクセスに対する動作は、この記事の時点では確認していません。11-03の
deploy.jsは、この記事の初版(文字列の埋め込み版)のコピーであり、この記事の修正はまだ反映していません(11-03の扱いは別工程で判断します)。
