feat: generate repository rename adoption plans
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 25s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a049a4-ee9f-78e1-9d66-2cb0f9bea3e3
This commit is contained in:
tegwick 2026-08-29 13:08:02 +02:00
parent bdf3a1fdf8
commit ef0b6df3b8
7 changed files with 1294 additions and 5 deletions

View file

@ -388,3 +388,86 @@ def test_human_status_distinguishes_lifecycle_states(
_run(monkeypatch, "repo", "rename", "status", OPERATION_ID)
captured = capsys.readouterr()
assert f"{label}: repository rename status" in captured.out + captured.err
def test_generate_workplan_cli_writes_once_and_reports_contract(
monkeypatch, tmp_path, capsys
):
repo_root = tmp_path / "flex-auth"
repo_root.mkdir()
(repo_root / "AGENTS.md").write_text(
"**Workplan prefix:** `FLEX-WP-`\n"
)
output = repo_root / "workplans" / "rename.md"
report = {
"schema_version": "state-hub.repository-rename-preflight.v1",
"repo_id": REPO_ID,
"old_slug": "flex-auth",
"new_slug": "access-engine",
"safe_to_apply": True,
"blockers": [],
"warnings": [],
"report_checksum": "a" * 64,
"preflight_token": "private-token",
"preflighted_at": "2026-08-29T08:00:00Z",
"current": {
"statehub": {"local_path": str(repo_root), "host_paths": {}},
"forge_identity": {
"verification_state": "verified",
"forge_repository_id": 42,
},
"forge_available": True,
"forge": {
"repository_id": 42,
"default_branch": "main",
"head_commit": "b" * 40,
},
},
"active_work": {"workplans": [], "tasks": []},
"affected": {"external_handoffs": []},
}
repo = {**_repo(), "local_path": str(repo_root), "host_paths": {}}
workplans = [
{
"slug": "flex-wp-0018",
"backing_filename": "FLEX-WP-0018-last.md",
"status": "finished",
}
]
def request(_api_base, method, path, body=None, *, expected=dict):
del body
if path.startswith("/repos/flex-auth"):
return repo
if path.startswith("/workplans/"):
assert expected is list
return workplans
assert method == "POST"
return report
monkeypatch.setattr(rename_cli, "_api_request", request)
args = (
"repo",
"rename",
"generate-workplan",
"flex-auth",
"access-engine",
"--repo-path",
str(repo_root),
"--output",
str(output),
"--json",
)
_run(monkeypatch, *args)
result = json.loads(capsys.readouterr().out)
assert result["state"] == "achieved"
assert result["result"]["workplan_id"] == "FLEX-WP-0019"
assert result["result"]["workplan_prefix"] == "FLEX-WP"
assert result["result"]["state_hub_uuid_fields_written"] == []
assert "private-token" not in output.read_text()
with pytest.raises(SystemExit) as exc:
_run(monkeypatch, *args)
assert exc.value.code == 1
refused = json.loads(capsys.readouterr().out)
assert refused["error"]["code"] == "output_exists"

View file

@ -0,0 +1,323 @@
from __future__ import annotations
import hashlib
from pathlib import Path
import pytest
from repository_rename_workplan import (
WorkplanGenerationError,
build_generation_snapshot,
content_checksum,
default_output_path,
render_workplan,
write_workplan_exclusive,
)
from scripts.quality_debt import collect as collect_quality_debt
from scripts.validate_repo_adr import validate
REPO_ID = "fda8ad85-a7d7-4055-8f21-902a533e59df"
def _repo(path: str | None = None, **extra) -> dict:
return {
"id": REPO_ID,
"slug": "flex-auth",
"canonical_slug": "flex-auth",
"domain_slug": "infotech",
"local_path": path,
"host_paths": {},
"aliases": [],
**extra,
}
def _preflight(**extra) -> dict:
report = {
"schema_version": "state-hub.repository-rename-preflight.v1",
"repo_id": REPO_ID,
"old_slug": "flex-auth",
"new_slug": "access-engine",
"safe_to_apply": True,
"blockers": [],
"warnings": [],
"report_checksum": "a" * 64,
"preflight_token": "must-never-appear-in-workplan",
"preflighted_at": "2026-08-29T08:00:00Z",
"current": {
"statehub": {
"repo_id": REPO_ID,
"local_path": None,
"host_paths": {},
},
"forge_identity": {
"verification_state": "verified",
"forge_repository_id": 42,
"forge_owner": "coulomb",
},
"forge_available": True,
"forge": {
"repository_id": 42,
"default_branch": "main",
"head_commit": "b" * 40,
},
},
"active_work": {"workplans": [], "tasks": []},
"affected": {"external_handoffs": []},
}
report.update(extra)
return report
def _workplans() -> list[dict]:
return [
{
"id": "11111111-1111-4111-8111-111111111111",
"slug": "flex-wp-0017",
"status": "active",
"backing_filename": "FLEX-WP-0017-action-contract.md",
},
{
"id": "22222222-2222-4222-8222-222222222222",
"slug": "flex-wp-0018",
"status": "archived",
"backing_filename": "260828-FLEX-WP-0018-inbound-corrections.md",
"backing_archived": True,
},
]
def _repo_root(tmp_path: Path) -> Path:
root = tmp_path / "flex-auth"
root.mkdir()
(root / "AGENTS.md").write_text("**Workplan prefix:** `FLEX-WP-`\n")
return root
def test_flex_auth_snapshot_is_deterministic_and_complete(tmp_path):
root = _repo_root(tmp_path)
report = _preflight(
warnings=[
{
"code": "active_work_present",
"message": "coordinate NetKingdom security-stack work",
"workplan_count": 1,
}
],
affected={
"external_handoffs": [
"fabric-graph-projections",
"interface-change-consumers",
]
},
active_work={
"workplans": [
{
"id": "33333333-3333-4333-8333-333333333333",
"slug": "FLEX-WP-0017",
"status": "active",
}
],
"tasks": [
{
"id": "44444444-4444-4444-8444-444444444444",
"record_id": "FLEX-WP-0017-T05",
"status": "progress",
}
],
},
)
snapshot = build_generation_snapshot(
repo=_repo(str(root), aliases=["flexauth-legacy"]),
preflight=report,
workplans=_workplans(),
)
first = render_workplan(snapshot, owner="codex")
second = render_workplan(snapshot, owner="codex")
assert first == second
assert content_checksum(first) == hashlib.sha256(first.encode()).hexdigest()
assert snapshot.prefix == "FLEX-WP"
assert snapshot.workplan_id == "FLEX-WP-0019"
assert first.count("```task\n") == 11
assert "id: FLEX-WP-0019-T06\nstatus: wait" in first
assert "id: FLEX-WP-0019-T11\nstatus: wait" in first
assert "state_hub_workstream_id:" not in first
assert "state_hub_task_id:" not in first
assert "must-never-appear-in-workplan" not in first
assert "`active_work_present`" in first
assert "`fabric-graph-projections`" in first
assert "`interface-change-consumers`" in first
assert "FLEX_AUTH_*" in first
assert "NetKingdom policy consumers" in first
assert "flexauth-legacy" in first
assert "| Credential-route catalog | `ops-warden` |" in first
assert "only that repository closes" in first
def test_generated_snapshot_passes_parser_and_quality_debt(tmp_path):
root = _repo_root(tmp_path)
snapshot = build_generation_snapshot(
repo=_repo(str(root)),
preflight=_preflight(),
workplans=_workplans(),
)
content = render_workplan(snapshot, owner="codex")
output = default_output_path(snapshot)
write_workplan_exclusive(output, content)
report = validate(root, skip_api=True)
assert report.failures == []
assert collect_quality_debt(
root, api_base=None, include_hub_intakes=False
) == []
assert output.name.startswith("FLEX-WP-0019-")
def test_snapshot_counts_archived_workplans_when_allocating_id(tmp_path):
root = _repo_root(tmp_path)
snapshot = build_generation_snapshot(
repo=_repo(str(root)),
preflight=_preflight(),
workplans=[
{
"slug": "flex-wp-0004",
"status": "active",
"backing_filename": "FLEX-WP-0004-live.md",
},
{
"slug": "flex-wp-0099",
"status": "archived",
"backing_filename": "260101-FLEX-WP-0099-old.md",
"backing_archived": True,
},
],
)
assert snapshot.workplan_id == "FLEX-WP-0100"
assert snapshot.archived_workplan_ids == ("FLEX-WP-0099",)
def test_snapshot_renders_active_work_and_private_forge_failure(tmp_path):
root = _repo_root(tmp_path)
report = _preflight(
safe_to_apply=False,
blockers=[
{
"code": "forge_unreadable",
"message": "private repository could not be inspected",
}
],
current={
"statehub": {"repo_id": REPO_ID, "host_paths": {}},
"forge_identity": {"verification_state": "unverified"},
"forge_available": False,
"forge": None,
},
active_work={
"workplans": [
{"id": "active-uuid", "slug": "FLEX-WP-0017", "status": "active"}
],
"tasks": [],
},
)
snapshot = build_generation_snapshot(
repo=_repo(str(root)), preflight=report, workplans=_workplans()
)
rendered = render_workplan(snapshot, owner="codex")
assert "status: proposed" in rendered
assert "`forge_unreadable`" in rendered
assert "`forge-identity-unverified`" in rendered
assert "`forge-repository-unreadable`" in rendered
assert "workplan `FLEX-WP-0017` / `active-uuid` is `active`" in rendered
assert "id: FLEX-WP-0019-T06\nstatus: wait" in rendered
def test_snapshot_supports_missing_local_path_from_indexed_workplans(tmp_path):
missing = tmp_path / "not-mounted"
snapshot = build_generation_snapshot(
repo=_repo(str(missing)),
preflight=_preflight(),
workplans=_workplans(),
)
rendered = render_workplan(snapshot, owner="codex")
assert snapshot.prefix == "FLEX-WP"
assert snapshot.path_available is False
assert "`local-path-unavailable`" in rendered
with pytest.raises(WorkplanGenerationError) as exc:
default_output_path(snapshot)
assert exc.value.code == "repository_path_unavailable"
def test_snapshot_preserves_old_alias_context(tmp_path):
root = _repo_root(tmp_path)
snapshot = build_generation_snapshot(
repo=_repo(str(root), aliases=["old-flex", "flex-auth"]),
preflight=_preflight(),
workplans=_workplans(),
)
rendered = render_workplan(snapshot, owner="codex")
assert 'protected/current aliases: `["flex-auth", "old-flex"]`' in rendered
assert "Retain the protected `flex-auth` alias" in rendered
def test_existing_uuid_fields_are_untouched_and_not_copied_to_new_plan(tmp_path):
root = _repo_root(tmp_path)
workplans = root / "workplans"
workplans.mkdir()
existing = workplans / "FLEX-WP-0001-existing.md"
original = """---
id: FLEX-WP-0001
type: workplan
title: Existing
domain: infotech
status: active
owner: codex
created: "2026-01-01"
state_hub_workstream_id: "55555555-5555-4555-8555-555555555555"
---
"""
existing.write_text(original)
snapshot = build_generation_snapshot(
repo=_repo(str(root)), preflight=_preflight(), workplans=[]
)
rendered = render_workplan(snapshot, owner="codex")
assert existing.read_text() == original
assert "55555555-5555-4555-8555-555555555555" not in rendered
assert "state_hub_workstream_id:" not in rendered
def test_exclusive_writer_refuses_existing_output(tmp_path):
output = tmp_path / "existing.md"
output.write_text("operator content\n")
with pytest.raises(WorkplanGenerationError) as exc:
write_workplan_exclusive(output, "replacement\n")
assert exc.value.code == "output_exists"
assert output.read_text() == "operator content\n"
def test_prefix_is_never_derived_from_new_slug(tmp_path):
root = tmp_path / "repo"
root.mkdir()
snapshot = build_generation_snapshot(
repo=_repo(str(root)),
preflight=_preflight(),
workplans=_workplans(),
)
assert snapshot.prefix == "FLEX-WP"
assert not snapshot.workplan_id.startswith("ACCESS-ENGINE")
def test_ambiguous_indexed_prefixes_fail_closed(tmp_path):
root = tmp_path / "repo"
root.mkdir()
with pytest.raises(WorkplanGenerationError) as exc:
build_generation_snapshot(
repo=_repo(str(root)),
preflight=_preflight(),
workplans=[
{"slug": "flex-wp-0001"},
{"slug": "other-wp-0001"},
],
)
assert exc.value.code == "workplan_prefix_ambiguous"