From d4a195d0b5f8fbf4fd7c3a48f77d00db7fbbbfbf Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 23 May 2026 17:01:41 +0200 Subject: [PATCH] Add renormalization rule guide --- scripts/consistency_check.py | 71 +++++++++++++++++++ tests/test_consistency_check.py | 16 +++++ ...ifecycle-assertions-and-renormalization.md | 10 ++- 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/scripts/consistency_check.py b/scripts/consistency_check.py index a3114f3..b3bb25f 100644 --- a/scripts/consistency_check.py +++ b/scripts/consistency_check.py @@ -178,6 +178,38 @@ class ConsistencyReport: return [i for i in self.issues if i.severity == "INFO"] +@dataclass(frozen=True) +class RenormalizationRule: + check_id: str + invariant: str + detection: str + repair: str + test_anchor: str + + +RENORMALIZATION_RULES: tuple[RenormalizationRule, ...] = ( + RenormalizationRule( + check_id="C-23", + invariant="Planning-state workplans cannot contain active task work.", + detection=( + "Workplan status is proposed, ready, or backlog while a linked " + "task is in_progress or blocked." + ), + repair="Patch the DB workstream and workplan frontmatter to status=active.", + test_anchor="tests/test_consistency_check.py::TestLifecycleRenormalization", + ), +) + + +RENORMALIZATION_NEXT_GUARD_CHECKLIST: tuple[str, ...] = ( + "Name the invariant and assign the next C-id.", + "Add rule metadata to RENORMALIZATION_RULES.", + "Add detection in check_repo before generic drift rules that could fight it.", + "Add the repair branch in fix_repo, using file writes only through helpers.", + "Add detection and repair tests under TestLifecycleRenormalization.", +) + + @contextmanager def run_lock(name: str): """Hold a nonblocking process lock for long-running consistency modes.""" @@ -1999,6 +2031,24 @@ def archive_closed_workplans( # Output / rendering # --------------------------------------------------------------------------- +def render_renormalization_guide() -> str: + lines = ["Lifecycle Renormalization Rules", "=" * 33] + for rule in RENORMALIZATION_RULES: + lines.extend( + [ + "", + f"{rule.check_id}: {rule.invariant}", + f" Detect: {rule.detection}", + f" Repair: {rule.repair}", + f" Tests: {rule.test_anchor}", + ] + ) + lines.extend(["", "Add The Next Guard"]) + for idx, item in enumerate(RENORMALIZATION_NEXT_GUARD_CHECKLIST, 1): + lines.append(f" {idx}. {item}") + return "\n".join(lines) + + def render_text(report: ConsistencyReport, show_info: bool = True) -> str: SEP = "=" * 66 lines = [ @@ -2089,6 +2139,8 @@ def main() -> None: help="Run checks against all repos with a resolvable path on this host") group.add_argument("--here", metavar="PATH", nargs="?", const="", help="Infer repo slug from git remote URL at PATH (default: CWD)") + group.add_argument("--renormalization-guide", action="store_true", + help="Print lifecycle renormalization rules and the add-next-guard checklist") parser.add_argument("--fix", action="store_true", help="Apply auto-fixable issues (status drift, repo mismatch, etc.)") parser.add_argument("--remote", action="store_true", @@ -2115,6 +2167,25 @@ def main() -> None: help="Output JSON instead of human-readable text") args = parser.parse_args() + if args.renormalization_guide: + if args.as_json: + print(json.dumps({ + "rules": [ + { + "check_id": rule.check_id, + "invariant": rule.invariant, + "detection": rule.detection, + "repair": rule.repair, + "test_anchor": rule.test_anchor, + } + for rule in RENORMALIZATION_RULES + ], + "add_next_guard": list(RENORMALIZATION_NEXT_GUARD_CHECKLIST), + }, indent=2)) + else: + print(render_renormalization_guide()) + sys.exit(0) + import os as _os no_wb = getattr(args, "no_writeback", False) do_fix = args.fix or args.remote diff --git a/tests/test_consistency_check.py b/tests/test_consistency_check.py index e174c72..2a0593e 100644 --- a/tests/test_consistency_check.py +++ b/tests/test_consistency_check.py @@ -24,6 +24,7 @@ from consistency_check import ( ConsistencyReport, Issue, FILE_TO_DB_WORKSTREAM_STATUS, + RENORMALIZATION_RULES, STATUS_ORDER, _BACKGROUND_CHECKS, _detect_behind_remote, @@ -41,6 +42,7 @@ from consistency_check import ( parse_frontmatter, parse_task_blocks, render_text, + render_renormalization_guide, report_to_dict, ) from api.workplan_status import ready_review_status @@ -377,6 +379,20 @@ class TestRenderText: assert "C-08" not in text +class TestRenormalizationGuide: + def test_registry_contains_c23_rule(self): + rule = next(rule for rule in RENORMALIZATION_RULES if rule.check_id == "C-23") + assert "Planning-state" in rule.invariant + assert "TestLifecycleRenormalization" in rule.test_anchor + + def test_guide_points_to_next_guard_pattern(self): + text = render_renormalization_guide() + assert "C-23" in text + assert "Add The Next Guard" in text + assert "Add detection in check_repo" in text + assert "Add the repair branch in fix_repo" in text + + # --------------------------------------------------------------------------- # report_to_dict # --------------------------------------------------------------------------- diff --git a/workplans/STATE-WP-0047-lifecycle-assertions-and-renormalization.md b/workplans/STATE-WP-0047-lifecycle-assertions-and-renormalization.md index bae3f6c..9c693b0 100644 --- a/workplans/STATE-WP-0047-lifecycle-assertions-and-renormalization.md +++ b/workplans/STATE-WP-0047-lifecycle-assertions-and-renormalization.md @@ -154,7 +154,7 @@ existing consistency sync loop. ```task id: STATE-WP-0047-T06 -status: todo +status: done priority: medium state_hub_task_id: "4b663fce-876c-4a52-955c-c754dbf44b0f" ``` @@ -165,6 +165,11 @@ turn that pattern into a new invariant, test, or consistency repair. Done when renormalization scaffolding has an explicit "add the next guard here" pattern instead of relying on ad hoc fixes. +Result 2026-05-23: added a renormalization rule registry and +`scripts/consistency_check.py --renormalization-guide`. The guide lists active +repair rules and the concise checklist for turning the next recognized drift +pattern into metadata, detection, repair, and tests. + ## T07 - Regression Tests ```task @@ -191,6 +196,9 @@ Progress 2026-05-23: added consistency checker coverage for lifecycle renormalization detection and repair, including a guard that C-23 takes precedence over generic C-04 status drift. +Progress 2026-05-23: added guide coverage so the drift-learning scaffold has a +stable test anchor. + ## Acceptance Criteria - Starting task work deterministically activates the parent workstream.