Allow bound historical suffix tasks during normal sync

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a087d8-d22d-7d11-8169-bf22a729dff1
This commit is contained in:
tegwick 2026-09-09 22:31:14 +02:00
parent 5ad49dd79e
commit 3db3e7e297
6 changed files with 241 additions and 6 deletions

View file

@ -850,10 +850,37 @@ def ensure_missing_work_record_identifiers(
repo_root = repo_root.resolve()
namespace = namespace or load_fleet_namespace()
identity = scan_record_identities(repo_root)
if identity["invalid_identifiers"] or identity["identity_collisions"]:
# Completed, already-bound suffix tasks are historical evidence, not
# allocation candidates. Keep conformance reporting strict while allowing
# ordinary registration to preserve those bindings. Local aliases still
# require the explicit parent allowlist in the kind registry.
historical_sources: set[str] = set()
for path in iter_workplan_files(repo_root):
parsed = parse_workplan_file(path, repo_root=repo_root)
if parsed.status not in {"finished", "archived", "completed"} or not parsed.id:
continue
for number, task in enumerate(parsed.tasks, start=1):
if task.status not in {"done", "cancel"} or not task.state_hub_task_id:
continue
if not re.fullmatch(re.escape(parsed.id) + r"-T[0-9]{2}[a-z]", task.id or ""):
continue
try:
uuid.UUID(task.state_hub_task_id)
except ValueError:
continue
historical_sources.add(f"{parsed.path}#task-block-{number}")
invalid = [
item for item in identity["invalid_identifiers"]
if item["source"] not in historical_sources
]
historical = [
item for item in identity["invalid_identifiers"]
if item["source"] in historical_sources
]
if invalid or identity["identity_collisions"]:
raise ValueError(
"work-record identities are not safe to derive: "
f"invalid={identity['invalid_identifiers']!r}, "
f"invalid={invalid!r}, "
f"collisions={identity['identity_collisions']!r}"
)
@ -926,6 +953,7 @@ def ensure_missing_work_record_identifiers(
"repo": repo_root.name,
"namespace": namespace,
"assignments": assignments,
"historical_invalid_identifiers": historical,
"files_changed": sorted(str(path.relative_to(repo_root)) for path in rendered),
}