--- cs:140/Editor/ServiceSimStageB.cs
+++ cs:141/Editor/ServiceSimStageB.cs
@@ -92,33 +92,36 @@
             BuildOrder(out condIdx, out seeds);
 
             string ledger = ServiceSimLedger.PathOf(plan);
-            HashSet<string> done = ServiceSimLedger.DoneFolders(ledger);
             string day = DateTime.Now.ToString("yyyyMMdd");
 
+            // --- 回し始めの版（照合キーに入れるので先に読む。依頼 v8 の 3）---
+            string cs, pendingNote;
+            ReadChangeset(out cs, out pendingNote);
+
+            // 照合は「店・台数・種・版」。出力フォルダ名（日付入り）では照らし合わせない
+            HashSet<string> done = ServiceSimLedger.DoneKeys(ledger);
+
             List<string> conds = new List<string>();
             List<string> folders = new List<string>();
             int skipped = 0;
             for (int i = 0; i < condIdx.Count; i++)
             {
                 SimParams.Condition c = sp.ConditionAt(condIdx[i]);
-                string folder = FolderName(day, c, seeds[i]);
-                if (done.Contains(folder)) { skipped++; continue; }
+                if (done.Contains(ServiceSimLedger.RunKey(c.store, c.robots, seeds[i], cs)))
+                { skipped++; continue; }
                 conds.Add(condIdx[i] + ":" + seeds[i]);
-                folders.Add(folder);
+                folders.Add(FreeFolderName(plan, day, cs, c, seeds[i]));
             }
 
             if (conds.Count == 0)
             {
-                Debug.Log("[ServiceSim] 段階B：18回ぜんぶ台帳にあります（" + skipped + " 回を飛ばしました）。" +
+                Debug.Log("[ServiceSim] 段階B：この版（" + cs + "）の18回はぜんぶ台帳にあります（" +
+                          skipped + " 回を飛ばしました）。" +
                           "\n  やり直すときは台帳の行を見て、エイイチに相談してください" +
                           "\n  台帳: " + ledger);
                 return;
             }
 
-            // --- 回し始めの記録 ---
-            string cs, pendingNote;
-            ReadChangeset(out cs, out pendingNote);
-
             EditorPrefs.SetBool(KeyActive, true);
             EditorPrefs.SetInt(KeyIndex, 0);
             EditorPrefs.SetString(KeyConds, string.Join(";", conds.ToArray()));
@@ -242,10 +245,34 @@
             seeds.Add(s);
         }
 
-        static string FolderName(string day, SimParams.Condition c, int seed)
+        /// <summary>
+        /// 出力フォルダの名前（依頼 v8 の 3）。
+        /// {日付}_stageB_cs{版}_{店}_r{台数}_s{種}。
+        /// 版が分かるようにしておき、照合は台帳のキー（店・台数・種・版）で行う
+        /// </summary>
+        static string FolderName(string day, string cs, SimParams.Condition c, int seed)
         {
-            // 台帳の照合キー。回し直しても同じ名前になるよう、時刻は入れない
-            return day + "_stageB_" + c.store + "_r" + c.robots + "_s" + seed;
+            // "cs:139" の ":" はフォルダ名に向かないので外す
+            string ver = (cs ?? "").Replace("cs:", "").Replace(":", "").Replace("（", "").Replace("）", "");
+            if (ver.Length == 0) ver = "unknown";
+            return day + "_stageB_cs" + ver + "_" + c.store + "_r" + c.robots + "_s" + seed;
+        }
+
+        /// <summary>
+        /// 書き出す先が既にあるときは上書きせず、末尾に _2・_3 … を付けた
+        /// 新しいフォルダ名を返す（依頼 v8 の 3）
+        /// </summary>
+        static string FreeFolderName(ExperimentPlan plan, string day, string cs,
+                                     SimParams.Condition c, int seed)
+        {
+            string baseName = FolderName(day, cs, c, seed);
+            string name = baseName;
+            for (int n = 2; n < 100; n++)
+            {
+                if (!Directory.Exists(Path.Combine(plan.kioxiaOutputRoot, name))) return name;
+                name = baseName + "_" + n;
+            }
+            return name;
         }
 
         // ---------------- 1回ずつ回す ----------------
@@ -644,26 +671,38 @@
             pendingNote = "";
 
             string outp = RunCm("status --machinereadable");
-            if (!string.IsNullOrEmpty(outp))
+            if (string.IsNullOrEmpty(outp))
             {
-                int n = 0;
-                string[] lines = outp.Split('\n');
-                for (int i = 0; i < lines.Length; i++)
+                // cm を呼べなかった。数が分からないので「不明」と書く（依頼 v8 の 3）
+                cs = "不明";
+                pendingNote = "不明（cm status を読めませんでした）";
+                return;
+            }
+
+            // 保留の数は Unity Version Control の「保留中の変更」と同じ数え方にする。
+            // 置いてあるだけ（PR＝Private）も、あの一覧には出るので **数に入れる**
+            // （前は PR を外していたので、2件あったのに空になっていた）
+            int controlled = 0, privateItems = 0;
+            string[] lines = outp.Split('\n');
+            for (int i = 0; i < lines.Length; i++)
+            {
+                string l = lines[i].Trim();
+                if (l.Length == 0) continue;
+                if (l.StartsWith("STATUS "))
                 {
-                    string l = lines[i].Trim();
-                    if (l.Length == 0) continue;
-                    if (l.StartsWith("STATUS "))
-                    {
-                        string[] f = l.Split(' ');
-                        if (f.Length > 1) cs = "cs:" + f[1];
-                        continue;
-                    }
-                    if (l.StartsWith("PR ")) continue;         // 置いてあるだけ
-                    n++;
+                    string[] f = l.Split(' ');
+                    if (f.Length > 1) cs = "cs:" + f[1];
+                    continue;
                 }
-                if (n > 0) pendingNote = "保留あり " + n + " 件";
+                if (l.StartsWith("PR ")) privateItems++;
+                else controlled++;
             }
-            if (cs.Length == 0) cs = "（読めません）";
+
+            int all = controlled + privateItems;
+            if (all > 0)
+                pendingNote = "保留あり " + all + " 件（管理下 " + controlled +
+                              " 件・置いてあるだけ " + privateItems + " 件）";
+            if (cs.Length == 0) cs = "不明";
         }
 
         static string RunCm(string args)
