* feat(workbench): add construction evidence read model scaffolding * feat(workbench-ui): add construction evidence TS types * feat(workbench): add construction evidence journal projector * test(workbench): cover construction evidence read model * feat(workbench-ui): add construction evidence view helpers * test(workbench-ui): cover construction evidence view helpers * feat(workbench): add generalization audit evidence scaffolding * test(workbench): cover generalization audit evidence view * feat(workbench-ui): add generalization evidence TS types * feat(workbench-ui): add generalization evidence view helpers * test(workbench-ui): cover generalization evidence helpers * feat(workbench): add proposal artifact authority scaffolding * test(workbench): cover proposal artifact authority rules * feat(workbench-ui): add proposal artifact TS types * feat(workbench-ui): add proposal artifact view helpers * test(workbench-ui): cover proposal artifact view helpers * feat(workbench): add demo narrative evidence scaffolding * test(workbench): cover demo narrative scaffolding * feat(workbench-ui): add demo narrative TS types * feat(workbench-ui): add demo narrative view helpers * test(workbench-ui): cover demo narrative view helpers * fix(evals): resolve discovery_candidates.jsonl via EngineStateStore
122 lines
3.8 KiB
Python
122 lines
3.8 KiB
Python
"""ProposalArtifact authority scaffolding for Workbench.
|
|
|
|
This module defines a shared proposal-review envelope without admitting any new
|
|
ratification handler. It is safe, inert UI/read-model substrate: capability level
|
|
controls what the Workbench may display as an affordance.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Literal
|
|
|
|
ProposalCapabilityLevel = Literal[
|
|
"inspect_only",
|
|
"proposal_only",
|
|
"ratification_enabled",
|
|
]
|
|
|
|
ProposalArtifactState = Literal[
|
|
"pending",
|
|
"accepted",
|
|
"rejected",
|
|
"withdrawn",
|
|
"deferred",
|
|
"unknown",
|
|
]
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ProposalSubject:
|
|
kind: str
|
|
subject_id: str
|
|
display_name: str
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class EvidencePointer:
|
|
kind: str
|
|
ref: str
|
|
label: str
|
|
digest: str | None = None
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ProposalValidationReport:
|
|
status: Literal["valid", "blocked", "unknown"]
|
|
blockers: list[str] = field(default_factory=list)
|
|
warnings: list[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ProposalSafetyReport:
|
|
status: Literal["clear", "warning", "failed", "unknown"]
|
|
disclosures: list[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class ProposalArtifact:
|
|
proposal_id: str
|
|
subject: ProposalSubject
|
|
state: ProposalArtifactState
|
|
capability_level: ProposalCapabilityLevel
|
|
source_kind: str
|
|
proposed_change: Any = None
|
|
reasoning_trace: Any = None
|
|
evidence_pointers: list[EvidencePointer] = field(default_factory=list)
|
|
validation: ProposalValidationReport | None = None
|
|
replay_evidence: Any = None
|
|
safety_report: ProposalSafetyReport | None = None
|
|
affected_artifacts: list[EvidencePointer] = field(default_factory=list)
|
|
handler_route: str | None = None
|
|
suggested_cli: str | None = None
|
|
audit_refs: list[EvidencePointer] = field(default_factory=list)
|
|
ui_disclosure: str = "Proposal artifact is inspect-only unless an admitted handler exists."
|
|
|
|
|
|
def ratification_affordance_allowed(artifact: ProposalArtifact) -> bool:
|
|
"""Return whether UI may show ratify/reject/defer controls."""
|
|
|
|
return artifact.capability_level == "ratification_enabled" and bool(
|
|
artifact.handler_route
|
|
)
|
|
|
|
|
|
def capability_disclosure(artifact: ProposalArtifact) -> str:
|
|
if artifact.capability_level == "ratification_enabled":
|
|
if artifact.handler_route:
|
|
return "Ratification controls may render through the admitted handler route."
|
|
return "Ratification is disabled because no handler route is present."
|
|
if artifact.capability_level == "proposal_only":
|
|
return "Proposal-only artifact: review/export/copy are allowed; apply is not."
|
|
return "Inspect-only artifact: no apply, ratify, promote, or mutation affordance is allowed."
|
|
|
|
|
|
def proposal_artifact_from_minimal(
|
|
*,
|
|
proposal_id: str,
|
|
subject_kind: str,
|
|
subject_id: str,
|
|
display_name: str,
|
|
source_kind: str,
|
|
capability_level: ProposalCapabilityLevel = "inspect_only",
|
|
state: ProposalArtifactState = "unknown",
|
|
handler_route: str | None = None,
|
|
) -> ProposalArtifact:
|
|
"""Build a minimal shared proposal review envelope."""
|
|
|
|
artifact = ProposalArtifact(
|
|
proposal_id=proposal_id,
|
|
subject=ProposalSubject(
|
|
kind=subject_kind,
|
|
subject_id=subject_id,
|
|
display_name=display_name,
|
|
),
|
|
state=state,
|
|
capability_level=capability_level,
|
|
source_kind=source_kind,
|
|
handler_route=handler_route,
|
|
)
|
|
if capability_level != "ratification_enabled" and handler_route is not None:
|
|
raise ValueError("handler_route requires ratification_enabled capability")
|
|
return artifact
|