8FS-539 regression coverage — :func:`oct.migrate.oct_migrate.run_migrate_option_c`
9relocates legacy artefacts into ``.option_c/`` and writes ``oc_status.json``.
13- dry-run is side-effect-free.
14- Each legacy artefact is copied (not moved) to ``.option_c/``.
15- A ``.bk`` backup is created when the destination exists and differs.
16- ``oc_status.json`` records ``migrated_from`` and pillar enablement.
17- An idempotent second run skips already-migrated artefacts.
18- An unmigrated project with no legacy artefacts produces "nothing to
26 L3 — assertion details
31- All migration operations use ``tmp_path`` as the project root; no
32 real project files are touched.
35from __future__
import annotations
38from pathlib
import Path
46 """Create a minimal legacy Option C project layout."""
47 (root /
".octrc.json").write_text(
48 json.dumps({
"linter": {
"profile":
"compact"}}), encoding=
"utf-8",
50 (root /
"oc_diagnostics").mkdir()
51 (root /
"oc_diagnostics" /
"debug_config.json").write_text(
52 json.dumps({
"_schema_version":
"2.0",
"DEBUG_LEVELS": {}}),
55 (root /
"logs").mkdir()
56 (root /
"logs" /
"audit.jsonl").write_text(
"line1\n", encoding=
"utf-8")
57 (root /
"docs").mkdir()
58 (root /
"tests").mkdir()
64 result = run_migrate_option_c(tmp_path, dry_run=
True)
66 assert not (tmp_path /
".option_c").exists()
67 assert any(
"[DRY RUN]" in m
for m
in result.messages)
71 result = run_migrate_option_c(tmp_path, dry_run=
True)
73 msgs =
"\n".join(result.messages)
74 assert "octrc" in msgs
75 assert "debug_config" in msgs
82 result = run_migrate_option_c(tmp_path)
84 oc = tmp_path /
".option_c"
85 assert (oc /
"octrc.json").is_file()
86 assert (oc /
"debug_config.json").is_file()
87 assert (oc /
"logs").is_dir()
88 assert (oc /
"logs" /
"audit.jsonl").is_file()
89 assert len(result.copied) == 3
93 run_migrate_option_c(tmp_path)
95 assert (tmp_path /
".octrc.json").is_file()
96 assert (tmp_path /
"oc_diagnostics" /
"debug_config.json").is_file()
97 assert (tmp_path /
"logs" /
"audit.jsonl").is_file()
101 run_migrate_option_c(tmp_path)
103 assert (tmp_path /
".option_c" /
"cache").is_dir()
109 oc = tmp_path /
".option_c"
111 (oc /
"octrc.json").write_text(
'{"old": true}', encoding=
"utf-8")
113 result = run_migrate_option_c(tmp_path)
115 assert (oc /
"octrc.json.bk").is_file()
116 bk_data = json.loads(
117 (oc /
"octrc.json.bk").read_text(encoding=
"utf-8")
119 assert bk_data == {
"old":
True}
120 assert any(oc /
"octrc.json.bk" == p
for p
in result.backed_up)
124 oc = tmp_path /
".option_c"
126 (oc /
"octrc.json").write_text(
'{"old": true}', encoding=
"utf-8")
128 result = run_migrate_option_c(tmp_path, no_backup=
True)
130 assert not (oc /
"octrc.json.bk").exists()
131 assert result.backed_up == []
137 run_migrate_option_c(tmp_path)
139 path = tmp_path /
".option_c" /
"oc_status.json"
140 assert path.is_file()
141 raw = json.loads(path.read_text(encoding=
"utf-8"))
142 assert raw[
"_schema_version"] ==
"1.0"
143 assert raw[
"stage"]
in (
"bootstrap",
"migrating",
"compliant")
147 run_migrate_option_c(tmp_path)
150 (tmp_path /
".option_c" /
"oc_status.json").read_text(
154 mf = raw[
"migrated_from"]
155 assert mf[
"octrc"] ==
".octrc.json"
156 assert "debug_config" in mf
162 run_migrate_option_c(tmp_path)
163 second = run_migrate_option_c(tmp_path)
165 assert second.copied == []
167 reason ==
"already migrated" for _, reason
in second.skipped
173 result = run_migrate_option_c(tmp_path)
175 assert result.copied == []
177 reason ==
"not found" for _, reason
in result.skipped
test_backup_on_conflict(self, Path tmp_path)
test_no_backup_flag_skips_bk(self, Path tmp_path)
test_legacy_files_preserved(self, Path tmp_path)
test_cache_dir_created(self, Path tmp_path)
test_copies_all_artefacts(self, Path tmp_path)
test_dry_run_lists_all_artefacts(self, Path tmp_path)
test_dry_run_creates_nothing(self, Path tmp_path)
test_no_artefacts_found(self, Path tmp_path)
test_second_run_skips_identical(self, Path tmp_path)
test_migrated_from_records_sources(self, Path tmp_path)
test_oc_status_written(self, Path tmp_path)
None _seed_legacy_project(Path root)