plan --case: explicit reference-case render; WP-0005-T04 done; factor-issuer described
--allow-unimplemented (acknowledged type only, plan marked reference_case) lets the accepted Forgejo case render; reviewed now requires a live survey. WP-0005 lane applied and custody moved by the founder. keycape-factor-issuer filled from net-kingdom, rotation gap attributed to railiance-platform. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 327203@bnt-lap001 Assistant-Session: 55028ae3-4914-4bd1-8f5c-815f3527aef0
This commit is contained in:
parent
c6eb701c3d
commit
a3e97c8bd4
6 changed files with 71 additions and 20 deletions
|
|
@ -58,8 +58,13 @@ def _issues(validator, issues) -> list[str]:
|
|||
return [f"{i.path}: {i.message}" for i in issues if i.level == "ERROR"]
|
||||
|
||||
|
||||
def render(case_path: Path, nk_root: Path = DEFAULT_NK_ROOT, types_root: Path | None = None) -> tuple[dict, dict, dict]:
|
||||
"""Validate the case against its implemented type and render it. Returns (case, type, render)."""
|
||||
def render(case_path: Path, nk_root: Path = DEFAULT_NK_ROOT, types_root: Path | None = None,
|
||||
allow_unimplemented: bool = False) -> tuple[dict, dict, dict]:
|
||||
"""Validate the case against its implemented type and render it. Returns (case, type, render).
|
||||
|
||||
allow_unimplemented mirrors net-kingdom's validator flag: only the reference case
|
||||
that takes a type to `implemented` may render against an acknowledged type.
|
||||
"""
|
||||
v = load_validator(nk_root)
|
||||
case = yaml.safe_load(Path(case_path).read_text()) or {}
|
||||
types_root = types_root or nk_root / "security-case-types"
|
||||
|
|
@ -72,7 +77,10 @@ def render(case_path: Path, nk_root: Path = DEFAULT_NK_ROOT, types_root: Path |
|
|||
declarations, load_issues = v.composer.load_declarations(decls)
|
||||
if v.has_errors(load_issues):
|
||||
raise CasePlanError("type's provider declarations do not load", _issues(v, load_issues))
|
||||
issues, rendered = v.render_case(case, type_data, declarations, require_implemented=True)
|
||||
status = type_data.get("spec", {}).get("status")
|
||||
if allow_unimplemented and status != "acknowledged":
|
||||
raise CasePlanError(f"--allow-unimplemented applies only to an acknowledged type, not {status!r}")
|
||||
issues, rendered = v.render_case(case, type_data, declarations, require_implemented=not allow_unimplemented)
|
||||
if rendered is None:
|
||||
raise CasePlanError("case refused", _issues(v, issues))
|
||||
return case, type_data, rendered
|
||||
|
|
@ -155,15 +163,20 @@ def plan_document(case: dict, type_data: dict, rendered: dict, structure: Struct
|
|||
"credential_type": "security-case",
|
||||
"derived_from_type": rendered["type"],
|
||||
"render_digest": rendered["digest"],
|
||||
"status": "reviewed" if acc and not collisions else "draft",
|
||||
"status": "reviewed" if acc and not collisions and structure.source == "live" else "draft",
|
||||
"case_acceptance": acc,
|
||||
"reference_case": tspec.get("status") != "implemented",
|
||||
"approved_by": None,
|
||||
"approved_at": None,
|
||||
}
|
||||
lines = ["---", yaml.safe_dump(front, sort_keys=False).rstrip(), "---", "",
|
||||
f"# Construction plan (derived-from-type): {cspec['id']}", "",
|
||||
f"Rendered from `{rendered['type']}` ({tspec['title']}). Do not edit by hand:",
|
||||
f"re-run `ops-mason plan --case` instead. Render digest `{rendered['digest']}`.", "",
|
||||
f"re-run `ops-mason plan --case` instead. Render digest `{rendered['digest']}`.", ""]
|
||||
if tspec.get("status") != "implemented":
|
||||
lines += [f"**Reference case:** the type is `{tspec.get('status')}`, not yet `implemented`. This case",
|
||||
"is the one whose live materialization takes the type to `implemented`.", ""]
|
||||
lines += [
|
||||
"## 1. Demand", "", tspec["purpose"].strip(), "",
|
||||
"## 2. Existing-structure survey", "",
|
||||
f"Survey source: {structure.source} (metadata only).", ""]
|
||||
|
|
@ -191,8 +204,9 @@ def plan_document(case: dict, type_data: dict, rendered: dict, structure: Struct
|
|||
|
||||
|
||||
def plan_from_case(case_path: Path, *, nk_root: Path = DEFAULT_NK_ROOT, types_root: Path | None = None,
|
||||
structure: Structure | None = None, catalog: Path = DEFAULT_CATALOG) -> tuple[str, list[str], dict]:
|
||||
case, type_data, rendered = render(case_path, nk_root, types_root)
|
||||
structure: Structure | None = None, catalog: Path = DEFAULT_CATALOG,
|
||||
allow_unimplemented: bool = False) -> tuple[str, list[str], dict]:
|
||||
case, type_data, rendered = render(case_path, nk_root, types_root, allow_unimplemented)
|
||||
if structure is None:
|
||||
structure = live_structure(rendered, catalog)
|
||||
collisions = review(rendered, structure)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue