feat: DoX assessment recording and soft visibility (STATE-WP-0077)
Add quality_doc/dor/dod recording convention, quality-debt CLI, promote-intake and C-34 soft warnings, agent protocol notes, and DoD policy badge language. Mark STATE-WP-0077 finished.
This commit is contained in:
parent
d356fde41c
commit
fe4cfe22c9
13 changed files with 786 additions and 103 deletions
187
scripts/quality_assessment.py
Normal file
187
scripts/quality_assessment.py
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#!/usr/bin/env python3
|
||||
"""DoX quality assessment helpers (STATE-WP-0077).
|
||||
|
||||
Canonical recording fields and parsing for Definition assessments.
|
||||
See docs/work-record-quality-gates.md.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
POLICIES = ("DoC", "DoR", "DoD")
|
||||
|
||||
FIELD_FOR_POLICY = {
|
||||
"DoC": "quality_doc",
|
||||
"DoR": "quality_dor",
|
||||
"DoD": "quality_dod",
|
||||
}
|
||||
|
||||
|
||||
def _norm_policy(policy: str) -> str:
|
||||
p = policy.strip()
|
||||
upper = p.upper().replace(" ", "").replace("_", "")
|
||||
if upper in ("DOC", "COMPREHENSION", "DEFINITIONOFCOMPREHENSION"):
|
||||
return "DoC"
|
||||
if upper in ("DOR", "READY", "DEFINITIONOFREADY"):
|
||||
return "DoR"
|
||||
if upper in ("DOD", "DONE", "DEFINITIONOFDONE"):
|
||||
return "DoD"
|
||||
if p in POLICIES:
|
||||
return p
|
||||
raise ValueError(f"unknown policy {policy!r}; use DoC, DoR, or DoD")
|
||||
|
||||
|
||||
def badge(policy: str, outcome: str) -> str:
|
||||
"""Map policy + Ok|Failed (or full badge) to DoX-Ok / DoX-Failed."""
|
||||
pol = _norm_policy(policy)
|
||||
out = outcome.strip().strip('"')
|
||||
if out in (f"{pol}-Ok", f"{pol}-Failed"):
|
||||
return out
|
||||
if out.lower() in ("ok", "pass", "passed"):
|
||||
return f"{pol}-Ok"
|
||||
if out.lower() in ("failed", "fail", "no"):
|
||||
return f"{pol}-Failed"
|
||||
raise ValueError(f"unknown outcome {outcome!r} for {pol}")
|
||||
|
||||
|
||||
def assessment_from_mapping(meta: dict, policy: str) -> str | None:
|
||||
"""Read assessment badge for policy from frontmatter / YAML / task fields."""
|
||||
pol = _norm_policy(policy)
|
||||
key = FIELD_FOR_POLICY[pol]
|
||||
raw = meta.get(key)
|
||||
if raw is None:
|
||||
return None
|
||||
s = str(raw).strip().strip('"').strip("'")
|
||||
if not s or s.lower() in ("unassessed", "none", "null", "~", "-"):
|
||||
return None
|
||||
try:
|
||||
return badge(pol, s)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def is_ok(badge_value: str | None) -> bool:
|
||||
return bool(badge_value) and str(badge_value).endswith("-Ok")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class QualityDebtItem:
|
||||
kind: str
|
||||
record_id: str
|
||||
lifecycle_status: str
|
||||
missing: str
|
||||
path: str
|
||||
detail: str = ""
|
||||
|
||||
|
||||
def debt_for_workplan_meta(meta: dict, *, path: str) -> list[QualityDebtItem]:
|
||||
"""Quality debt for a workplan frontmatter dict."""
|
||||
items: list[QualityDebtItem] = []
|
||||
wp_id = str(meta.get("id", "")).strip() or path
|
||||
status = str(meta.get("status", "")).strip().lower()
|
||||
dor = assessment_from_mapping(meta, "DoR")
|
||||
dod = assessment_from_mapping(meta, "DoD")
|
||||
if status == "ready" and not is_ok(dor):
|
||||
items.append(
|
||||
QualityDebtItem(
|
||||
kind="workplan",
|
||||
record_id=wp_id,
|
||||
lifecycle_status=status,
|
||||
missing="DoR-Ok",
|
||||
path=path,
|
||||
detail=f"quality_dor={dor or 'unassessed'}",
|
||||
)
|
||||
)
|
||||
if status in ("finished", "completed") and not is_ok(dod):
|
||||
items.append(
|
||||
QualityDebtItem(
|
||||
kind="workplan",
|
||||
record_id=wp_id,
|
||||
lifecycle_status=status,
|
||||
missing="DoD-Ok",
|
||||
path=path,
|
||||
detail=f"quality_dod={dod or 'unassessed'}",
|
||||
)
|
||||
)
|
||||
return items
|
||||
|
||||
|
||||
def debt_for_intake_meta(meta: dict, *, path: str) -> list[QualityDebtItem]:
|
||||
"""Quality debt for intake blocks in vetted/routed without DoC-Ok."""
|
||||
items: list[QualityDebtItem] = []
|
||||
iid = str(meta.get("id", "")).strip() or path
|
||||
status = str(meta.get("status", "")).strip().lower()
|
||||
doc = assessment_from_mapping(meta, "DoC")
|
||||
if status in ("vetted", "routed") and not is_ok(doc):
|
||||
items.append(
|
||||
QualityDebtItem(
|
||||
kind="intake",
|
||||
record_id=iid,
|
||||
lifecycle_status=status,
|
||||
missing="DoC-Ok",
|
||||
path=path,
|
||||
detail=f"quality_doc={doc or 'unassessed'}",
|
||||
)
|
||||
)
|
||||
return items
|
||||
|
||||
|
||||
def intake_has_doc_ok(intake: dict) -> bool:
|
||||
"""Soft check: hub intake notes/description record DoC-Ok."""
|
||||
chunks: list[str] = []
|
||||
for key in ("description", "routed_note", "title"):
|
||||
v = intake.get(key)
|
||||
if v:
|
||||
chunks.append(str(v))
|
||||
for note in intake.get("notes") or []:
|
||||
if isinstance(note, dict):
|
||||
chunks.append(str(note.get("content") or ""))
|
||||
else:
|
||||
chunks.append(str(note))
|
||||
# structured future field
|
||||
if assessment_from_mapping(intake, "DoC") and is_ok(assessment_from_mapping(intake, "DoC")):
|
||||
return True
|
||||
text = "\n".join(chunks)
|
||||
if re.search(r"\bDoC-Ok\b", text):
|
||||
return True
|
||||
if re.search(r"quality_doc\s*[:=]\s*[\"']?(DoC-Ok|Ok)\b", text, re.I):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def progress_event_body(
|
||||
*,
|
||||
policy: str,
|
||||
outcome: str,
|
||||
record_kind: str,
|
||||
record_id: str,
|
||||
assessed_by: str | None = None,
|
||||
note: str | None = None,
|
||||
topic_id: str | None = None,
|
||||
workplan_id: str | None = None,
|
||||
author: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""JSON body for POST /progress/ recording a quality assessment."""
|
||||
b = badge(policy, outcome)
|
||||
pol = b.rsplit("-", 1)[0]
|
||||
body: dict[str, Any] = {
|
||||
"event_type": "quality_assessment",
|
||||
"summary": f"{b} for {record_kind} {record_id}",
|
||||
"author": author or assessed_by or "agent",
|
||||
"detail": {
|
||||
"policy": pol,
|
||||
"outcome": "Ok" if b.endswith("-Ok") else "Failed",
|
||||
"badge": b,
|
||||
"record_kind": record_kind,
|
||||
"record_id": record_id,
|
||||
"assessed_by": assessed_by,
|
||||
"note": note,
|
||||
},
|
||||
}
|
||||
if topic_id:
|
||||
body["topic_id"] = topic_id
|
||||
if workplan_id:
|
||||
body["workplan_id"] = workplan_id
|
||||
return body
|
||||
Loading…
Add table
Add a link
Reference in a new issue