公開・本番移行学習記事全11節Build

配置サンドボックスにアプリとデータを配置し、確認コマンドで確かめる

この記事で身につくこと配置対象と版を明確にし、手順と実行結果を記録する理由と、「配置できた」と「使える」が別であることを説明できる。

記事内目次(23項目)
この記事の管理情報(該当工程・関連要件・成果物の閲覧と保存・実行記録)
記事ID
11-02
該当工程
11-02 アプリとデータを配置する(関連:11-01、06-03、10-02、11-03、11-04)
関連要件
—
到達目標
配置対象と版を明確にし、手順と実行結果を記録する理由と、「配置できた」と「使える」が別であることを説明できる
主要な成果物
確認環境と検証状況
本文のコードは examples/11-02-deploy-record/ を正本とし、Claude Codeが2026-09-20にローカルで実行して stdout・stderr・終了コードを記録済み(macOS 26.6.2、Node.js v24.18.0)。配置元は08-01の正本と10-02の出力の実ファイル。実際の外部サービスへの配置は未検証。第5.4節の指示文と初稿は説明用の例。人による実読・内容確認は未実施。
未検証の範囲
実際の外部サービスへの配置、複数の利用者からの同時アクセスに対する動作は、この記事の時点では確認していない。
実行記録

正本の原稿にある管理表(記事ID・先に読むと理解しやすい記事・成果物パス・最終更新日など)は、この下の本文冒頭に「原稿の管理表」として開閉できる形で残しています。

原稿の管理表(13項目:記事ID・カテゴリ・要件ID・先に読むと理解しやすい記事・成果物パス・対象ツール・検証状況・最終更新日など)
管理項目内容
記事ID11-02
主な中カテゴリ11-02 アプリとデータを配置する
関連中カテゴリ11-01、06-03、10-02、11-03、11-04
関連要件ID—
先に読むと理解しやすい記事11-01(公開先と設定を確認する)、10-02(既存データの移行を準備する)を読んでいると理解しやすい。未読でも本文で必要な内容は説明する
到達目標配置対象と版を明確にし、手順と実行結果を記録する理由と、「配置できた」と「使える」が別であることを説明できる
3層の配置理解する=第3〜4節/作って確かめる=第5〜7節/設計を判断する=第8節
成果物パスtemplates/11-02-deploy-record_template.md、templates/11-02-deploy-record_example.md、examples/11-02-deploy-record/(deploy.js、run.js)、evidence_public/phase5b2b-2026-09-20/11-02/run_log.md
出典第11節参照
対象ツール・バージョン教材演習用にNode.js v24.18.0(node:fs・node:path・node:crypto のみ使用)
検証状況本文のコードは examples/11-02-deploy-record/ を正本とし、Claude Codeが2026-09-20にローカルで実行して stdout・stderr・終了コードを記録済み(第6〜7節、evidence_public/phase5b2b-2026-09-20/11-02/run_log.md)。実際の外部サービスへの配置は未検証。第5.4節の指示文と第6.1節の初稿は説明用の例であり、実際にAIへ送信・観測した記録ではない。人による実読・内容確認は未実施
残課題第11節参照
最終更新日2026-09-20(新規作成。同日、Phase 5B-2B:受入監査の「08-01のコードと10-02の移行データを『成果物として利用』と説明しながら、実際は deploy.js に文字列として埋め込んでいた」指摘に対し、前工程の実ファイルをコピーして配置し、配置元と内容の指紋(sha256)を記録・照合する形に改めた。読む順路・第4節の判断項目・第5.4節「AIに頼む」・第6節のレビューも追加)

この記事の会社・人物・データはすべて架空の設定です。実在する会社や案件とは関係ありません。この記事の「配置」は、教材演習用のローカルフォルダ(配置サンドボックス)への配置であり、実際の外部サービス(クラウド等)への配置ではありません。本文のコードは 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-sandboxexamples/08-01-minimal-example/approval.jscopyFileSync でコピー動作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.mdtemplates/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

自分の業務に使うときの手順は次のとおりです。

  1. 配置対象と版を明確にし、配置元を前工程の実ファイルで指す
  2. 配置手順を書き、確認コマンド(動作・同一性・件数・版)と期待結果を決める
  3. 実行できる範囲(配置サンドボックスなど)で実行し、配置記録(配置元と指紋)と実行記録に残す
  4. 実行しない項目(実際の外部サービスへの配置など)は未検証と明記する

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の扱いは別工程で判断します)。