fix: stop C-23 promoting proposed and C-15 overwriting files
ADR-007 / RMGR-WP-0005-T06: proposed stays a human gate. Task status follows the file (ADR-001); wait is not "ahead" of progress or todo.
This commit is contained in:
parent
aa45c9b6b0
commit
6d038fd050
2 changed files with 66 additions and 34 deletions
|
|
@ -19,7 +19,7 @@ Checks:
|
|||
C-12 orphan-db-task WARN Yes DB task in workstream has no file backing unless terminal in a closed workstream
|
||||
C-13 workstream-auto-complete WARN Yes All DB tasks done but workstream still active
|
||||
C-14 ghost-duplicate WARN No Active topic workstream with no repo_id matches a file-backed title — probable ghost from premature create_workstream() call
|
||||
C-15 task-db-ahead WARN Yes DB task status is ahead of file — regression prevented; writeback syncs file
|
||||
C-15 task-db-ahead WARN No DB task is terminal and file is not — report only; file wins (ADR-001)
|
||||
C-16 repo-behind-remote WARN No Local repo is behind remote tracking branch — --fix skipped to avoid clobbering remote progress
|
||||
C-17 repo-ahead-push-failed WARN No Local repo has unpushed commits and push failed — writes skipped to prevent runaway divergence
|
||||
C-19 workstream-planning-drift WARN Yes planning_priority/planning_order differs between file and DB
|
||||
|
|
@ -281,7 +281,10 @@ RENORMALIZATION_RULES: tuple[RenormalizationRule, ...] = (
|
|||
"Workplan status is proposed, ready, or backlog while a linked "
|
||||
"task is progress or wait."
|
||||
),
|
||||
repair="Patch the DB workstream and workplan frontmatter to status=active.",
|
||||
repair=(
|
||||
"ready/backlog: patch DB and file to active. "
|
||||
"proposed: report only (ADR-007 decision 3)."
|
||||
),
|
||||
test_anchor="tests/test_consistency_check.py::TestLifecycleRenormalization",
|
||||
),
|
||||
)
|
||||
|
|
@ -1302,18 +1305,27 @@ def check_repo(api_base: str, repo_slug: str, repo_path_override: str | None = N
|
|||
task_statuses=[*file_task_statuses, *db_task_statuses],
|
||||
)
|
||||
if active_task_requires_activation:
|
||||
# ADR-007 decision 3 / RMGR-WP-0005-T06: automation may report
|
||||
# that a proposed workplan has started work, but must not promote
|
||||
# proposed → active. proposed is a human review gate.
|
||||
proposed_gate = file_status == "proposed"
|
||||
report.add(
|
||||
severity="WARN",
|
||||
check_id="C-23",
|
||||
message=(
|
||||
f"Lifecycle drift in '{ws.get('slug')}': workplan status "
|
||||
f"{file_status!r} has an active task — repair to 'active'"
|
||||
f"{file_status!r} has an active task"
|
||||
+ (
|
||||
" — report only (ADR-007: do not auto-promote proposed)"
|
||||
if proposed_gate
|
||||
else " — repair to 'active'"
|
||||
)
|
||||
),
|
||||
file_path=fname,
|
||||
db_id=ws_id,
|
||||
file_value=file_status,
|
||||
db_value=ws.get("status", ""),
|
||||
fixable=True,
|
||||
fixable=not proposed_gate,
|
||||
_fix_context={
|
||||
"ws_id": ws_id,
|
||||
"wp_file": str(wp_file),
|
||||
|
|
@ -1544,48 +1556,45 @@ def check_repo(api_base: str, repo_slug: str, repo_path_override: str | None = N
|
|||
fixable=False,
|
||||
)
|
||||
continue
|
||||
# C-10 / C-15: task status drift
|
||||
# C-10 / C-15: task status drift. ADR-001: the file originates
|
||||
# work. Same-rank wait/progress is not "DB ahead" — writing
|
||||
# wait over progress/todo is the CFED/RMGR-WP-0004-T02 bug.
|
||||
# C-15 remains a report-only review signal when the DB is
|
||||
# terminal and the file is not.
|
||||
db_t_status = normalise_task_status(db_task.get("status", "todo"))
|
||||
if t_status and db_t_status and t_status != db_t_status:
|
||||
db_rank = STATUS_ORDER.get(db_t_status, 0)
|
||||
file_rank = STATUS_ORDER.get(t_status, 0)
|
||||
if db_rank >= file_rank:
|
||||
# C-15: DB is already at the same rank or ahead — prevent
|
||||
# regression. Writeback syncs the file to match DB.
|
||||
db_terminal = db_t_status in {"done", "cancel"}
|
||||
file_terminal = t_status in {"done", "cancel"}
|
||||
if db_terminal and not file_terminal:
|
||||
report.add(
|
||||
severity="WARN", check_id="C-15",
|
||||
message=(
|
||||
f"DB task '{t_id}' is ahead of file "
|
||||
f"DB task '{t_id}' is terminal "
|
||||
f"(db={db_t_status!r}, file={t_status!r}) "
|
||||
f"— regression prevented; writeback will sync file"
|
||||
f"— report only; file wins (ADR-001 / RMGR-WP-0005-T06)"
|
||||
),
|
||||
file_path=f"{fname}#{t_id}",
|
||||
db_id=t_sh_id,
|
||||
file_value=t_status,
|
||||
db_value=db_t_status,
|
||||
fixable=True,
|
||||
_fix_context={
|
||||
"task_id": t_sh_id,
|
||||
"wp_file": str(wp_file),
|
||||
"task_block_id": t_id,
|
||||
"db_status": db_t_status,
|
||||
},
|
||||
)
|
||||
else:
|
||||
# C-10: file is ahead — apply file→DB sync (normal drift)
|
||||
report.add(
|
||||
severity="WARN", check_id="C-10",
|
||||
message=(
|
||||
f"Task status drift '{t_id}': "
|
||||
f"file={t_status!r} db={db_t_status!r} (file wins)"
|
||||
),
|
||||
file_path=f"{fname}#{t_id}",
|
||||
db_id=t_sh_id,
|
||||
file_value=t_status,
|
||||
db_value=db_t_status,
|
||||
fixable=True,
|
||||
_fix_context={"task_id": t_sh_id, "status": t_status},
|
||||
fixable=False,
|
||||
)
|
||||
# File always wins, including same-rank wait ↔ progress.
|
||||
report.add(
|
||||
severity="WARN", check_id="C-10",
|
||||
message=(
|
||||
f"Task status drift '{t_id}': "
|
||||
f"file={t_status!r} db={db_t_status!r} (file wins)"
|
||||
),
|
||||
file_path=f"{fname}#{t_id}",
|
||||
db_id=t_sh_id,
|
||||
file_value=t_status,
|
||||
db_value=db_t_status,
|
||||
fixable=True,
|
||||
_fix_context={"task_id": t_sh_id, "status": t_status},
|
||||
)
|
||||
file_description = task.get("description")
|
||||
if isinstance(file_description, str):
|
||||
file_description = file_description.strip() or None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue