Add renormalization rule guide

This commit is contained in:
2026-05-23 17:01:41 +02:00
parent f3805eab79
commit d4a195d0b5
3 changed files with 96 additions and 1 deletions

View File

@@ -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