generated from coulomb/repo-seed
Add consumer alignment review kit
This commit is contained in:
@@ -9,6 +9,7 @@ from urllib.parse import parse_qs, urlparse
|
||||
|
||||
from .service import (
|
||||
CanonServiceError,
|
||||
alignment_template,
|
||||
artifact_graph,
|
||||
inspect_canon,
|
||||
list_artifacts,
|
||||
@@ -19,6 +20,7 @@ from .service import (
|
||||
profile_inspect,
|
||||
profile_validate,
|
||||
read_view,
|
||||
review_kit,
|
||||
validate_canon,
|
||||
)
|
||||
|
||||
@@ -84,6 +86,10 @@ def _route(
|
||||
return HTTPStatus.OK, list_models(root)
|
||||
if path == "/standards":
|
||||
return HTTPStatus.OK, list_standards(root)
|
||||
if path == "/review-kit":
|
||||
return HTTPStatus.OK, review_kit(root)
|
||||
if path == "/alignment-template":
|
||||
return HTTPStatus.OK, alignment_template(root)
|
||||
if path == "/validate":
|
||||
payload = validate_canon(root)
|
||||
return (HTTPStatus.OK if payload["ok"] else HTTPStatus.BAD_REQUEST), payload
|
||||
|
||||
@@ -10,6 +10,7 @@ from typing import Any
|
||||
from .api import serve
|
||||
from .service import (
|
||||
CanonServiceError,
|
||||
alignment_template,
|
||||
artifact_graph,
|
||||
generate_agent_briefs,
|
||||
generate_indexes,
|
||||
@@ -23,6 +24,7 @@ from .service import (
|
||||
profile_inspect,
|
||||
profile_validate,
|
||||
read_view,
|
||||
review_kit,
|
||||
validate_canon,
|
||||
write_validation_report,
|
||||
)
|
||||
@@ -53,6 +55,18 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
standards = sub.add_parser("standards", help="List canon standard artifacts")
|
||||
standards.set_defaults(handler=_standards)
|
||||
|
||||
review_kit_cmd = sub.add_parser(
|
||||
"review-kit",
|
||||
help="Read the consumer repository alignment review kit",
|
||||
)
|
||||
review_kit_cmd.set_defaults(handler=_review_kit)
|
||||
|
||||
alignment_template_cmd = sub.add_parser(
|
||||
"alignment-template",
|
||||
help="Read the consumer alignment workplan template",
|
||||
)
|
||||
alignment_template_cmd.set_defaults(handler=_alignment_template)
|
||||
|
||||
validate = sub.add_parser("validate", help="Validate the canon infospace")
|
||||
validate.add_argument(
|
||||
"--write",
|
||||
@@ -145,6 +159,14 @@ def _standards(args: argparse.Namespace) -> dict[str, Any]:
|
||||
return list_standards(_root(args))
|
||||
|
||||
|
||||
def _review_kit(args: argparse.Namespace) -> dict[str, Any]:
|
||||
return review_kit(_root(args))
|
||||
|
||||
|
||||
def _alignment_template(args: argparse.Namespace) -> dict[str, Any]:
|
||||
return alignment_template(_root(args))
|
||||
|
||||
|
||||
def _validate(args: argparse.Namespace) -> dict[str, Any]:
|
||||
if args.write:
|
||||
return write_validation_report(args.write, _root(args))
|
||||
|
||||
@@ -11,6 +11,10 @@ import yaml
|
||||
GENERATED_NOTICE = "<!-- GENERATED by info_tech_canon; do not edit by hand. -->"
|
||||
RETRIEVAL_ARTIFACT_KINDS = {
|
||||
"access-descriptor-set",
|
||||
"alignment-review-kit",
|
||||
"alignment-review-schema",
|
||||
"alignment-review-workflow",
|
||||
"alignment-scorecard",
|
||||
"benefit-analysis",
|
||||
"benchmark-findings",
|
||||
"benchmark-workspace",
|
||||
@@ -21,6 +25,7 @@ RETRIEVAL_ARTIFACT_KINDS = {
|
||||
"concept-catalog",
|
||||
"conformance-pack",
|
||||
"consumer-workplan-brief",
|
||||
"consumer-workplan-template",
|
||||
"evaluation-pack",
|
||||
"evaluation-question-set",
|
||||
"example",
|
||||
@@ -31,6 +36,7 @@ RETRIEVAL_ARTIFACT_KINDS = {
|
||||
"mapping-expectation",
|
||||
"model",
|
||||
"model-extension",
|
||||
"model-selection-guide",
|
||||
"native-concept-map",
|
||||
"pattern",
|
||||
"profile-alignment",
|
||||
@@ -876,6 +882,14 @@ def _summary_for_artifact(artifact: Any) -> str:
|
||||
return f"Example artifact for the {artifact.provenance.get('profile', 'unknown')} profile: {artifact.title}."
|
||||
if artifact.kind == "access-descriptor-set":
|
||||
return f"Structured CARING access descriptor set: {artifact.title}."
|
||||
if artifact.kind == "alignment-review-kit":
|
||||
return f"Reusable kit for consumer repository alignment reviews: {artifact.title}."
|
||||
if artifact.kind == "alignment-review-schema":
|
||||
return f"Schema for structured consumer repository alignment reviews: {artifact.title}."
|
||||
if artifact.kind == "alignment-review-workflow":
|
||||
return f"Repeatable workflow for canon alignment reviews: {artifact.title}."
|
||||
if artifact.kind == "alignment-scorecard":
|
||||
return f"Scorecard dimensions for canon alignment reviews: {artifact.title}."
|
||||
if artifact.kind == "benefit-analysis":
|
||||
return f"Consumer benefit analysis against canon surfaces: {artifact.title}."
|
||||
if artifact.kind == "benchmark-findings":
|
||||
@@ -896,6 +910,8 @@ def _summary_for_artifact(artifact: Any) -> str:
|
||||
return f"Machine-readable canon-side conformance support pack: {artifact.title}."
|
||||
if artifact.kind == "consumer-workplan-brief":
|
||||
return f"Consumer repo workplan seed brief: {artifact.title}."
|
||||
if artifact.kind == "consumer-workplan-template":
|
||||
return f"Template for consumer repository alignment workplans: {artifact.title}."
|
||||
if artifact.kind == "evaluation-pack":
|
||||
return f"Machine-readable canon-side evaluation pack: {artifact.title}."
|
||||
if artifact.kind == "evaluation-question-set":
|
||||
@@ -912,6 +928,8 @@ def _summary_for_artifact(artifact: Any) -> str:
|
||||
return f"Expected mappings between consumer graph capture and canon surfaces: {artifact.title}."
|
||||
if artifact.kind == "model-extension":
|
||||
return f"Candidate extension to an existing canon model: {artifact.title}."
|
||||
if artifact.kind == "model-selection-guide":
|
||||
return f"Guide for choosing canon models, standards, profiles, and benchmarks: {artifact.title}."
|
||||
if artifact.kind == "native-concept-map":
|
||||
return f"Native source concept map for assimilation or benchmark work: {artifact.title}."
|
||||
if artifact.kind == "pattern":
|
||||
|
||||
@@ -6,6 +6,8 @@ from pathlib import Path
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
|
||||
from . import generation
|
||||
from . import profiles
|
||||
from .bench import (
|
||||
@@ -22,6 +24,15 @@ from .validation import structural_checks
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
DEFAULT_INFOSPACE_ROOT = REPO_ROOT / "infospace"
|
||||
|
||||
REVIEW_KIT_COMPONENTS = {
|
||||
"manifest": "agent/review-kit/review-kit.yaml",
|
||||
"workflow": "agent/review-kit/review-workflow.yaml",
|
||||
"scorecard": "agent/review-kit/scorecard.yaml",
|
||||
"model_selection_guide": "agent/review-kit/model-selection-guide.yaml",
|
||||
"schema": "schemas/alignment-review.schema.yaml",
|
||||
}
|
||||
ALIGNMENT_TEMPLATE_PATH = "agent/templates/consumer-alignment-workplan.template.md"
|
||||
|
||||
|
||||
class CanonServiceError(Exception):
|
||||
def __init__(
|
||||
@@ -120,6 +131,45 @@ def list_standards(root: Path | str | None = None) -> dict[str, Any]:
|
||||
return list_artifacts(root, kind="standard")
|
||||
|
||||
|
||||
def review_kit(root: Path | str | None = None) -> dict[str, Any]:
|
||||
context = load_context(root)
|
||||
components = {
|
||||
name: {
|
||||
"path": relative,
|
||||
"content": _read_yaml_component(context.infospace_root, relative),
|
||||
}
|
||||
for name, relative in REVIEW_KIT_COMPONENTS.items()
|
||||
}
|
||||
template = alignment_template(root)
|
||||
return {
|
||||
"ok": True,
|
||||
"review_kit": components["manifest"]["content"],
|
||||
"components": components,
|
||||
"template": {
|
||||
"path": template["path"],
|
||||
"content": template["content"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def alignment_template(root: Path | str | None = None) -> dict[str, Any]:
|
||||
context = load_context(root)
|
||||
path = context.infospace_root / ALIGNMENT_TEMPLATE_PATH
|
||||
try:
|
||||
content = path.read_text(encoding="utf-8")
|
||||
except FileNotFoundError as exc:
|
||||
raise CanonServiceError(
|
||||
"missing_alignment_template",
|
||||
"Consumer alignment workplan template not found.",
|
||||
{"path": str(path)},
|
||||
) from exc
|
||||
return {
|
||||
"ok": True,
|
||||
"path": ALIGNMENT_TEMPLATE_PATH,
|
||||
"content": content,
|
||||
}
|
||||
|
||||
|
||||
def validate_canon(root: Path | str | None = None) -> dict[str, Any]:
|
||||
context = load_context(root)
|
||||
errors: list[dict[str, Any]] = []
|
||||
@@ -311,6 +361,25 @@ def read_view(name: str, root: Path | str | None = None) -> dict[str, Any]:
|
||||
) from exc
|
||||
|
||||
|
||||
def _read_yaml_component(infospace_root: Path, relative: str) -> Any:
|
||||
path = infospace_root / relative
|
||||
try:
|
||||
with path.open("r", encoding="utf-8") as handle:
|
||||
return yaml.safe_load(handle) or {}
|
||||
except FileNotFoundError as exc:
|
||||
raise CanonServiceError(
|
||||
"missing_review_kit_component",
|
||||
f"Review kit component not found: {relative}",
|
||||
{"path": str(path)},
|
||||
) from exc
|
||||
except yaml.YAMLError as exc:
|
||||
raise CanonServiceError(
|
||||
"invalid_review_kit_component",
|
||||
f"Review kit component is not valid YAML: {relative}",
|
||||
{"path": str(path), "reason": str(exc)},
|
||||
) from exc
|
||||
|
||||
|
||||
def _artifact_to_dict(
|
||||
artifact: KnowledgeArtifact,
|
||||
infospace_root: Path,
|
||||
|
||||
@@ -50,10 +50,15 @@ REQUIRED_SCHEMAS = (
|
||||
"interface-card.schema.yaml",
|
||||
"agent-brief.schema.yaml",
|
||||
"workplan.schema.yaml",
|
||||
"alignment-review.schema.yaml",
|
||||
)
|
||||
|
||||
RETRIEVAL_BRIEF_KINDS = {
|
||||
"access-descriptor-set",
|
||||
"alignment-review-kit",
|
||||
"alignment-review-schema",
|
||||
"alignment-review-workflow",
|
||||
"alignment-scorecard",
|
||||
"benefit-analysis",
|
||||
"benchmark-findings",
|
||||
"benchmark-workspace",
|
||||
@@ -64,6 +69,7 @@ RETRIEVAL_BRIEF_KINDS = {
|
||||
"concept-catalog",
|
||||
"conformance-pack",
|
||||
"consumer-workplan-brief",
|
||||
"consumer-workplan-template",
|
||||
"evaluation-pack",
|
||||
"evaluation-question-set",
|
||||
"example",
|
||||
@@ -73,6 +79,7 @@ RETRIEVAL_BRIEF_KINDS = {
|
||||
"mapping-expectation",
|
||||
"model",
|
||||
"model-extension",
|
||||
"model-selection-guide",
|
||||
"native-concept-map",
|
||||
"pattern",
|
||||
"profile-alignment",
|
||||
@@ -282,6 +289,62 @@ CARING_K8S_REQUIRED_DESCRIPTOR_CLASSES = {
|
||||
"induced_access",
|
||||
}
|
||||
|
||||
ALIGNMENT_REVIEW_KIT_ARTIFACT_IDS = {
|
||||
"review-kit/alignment",
|
||||
"review-kit/alignment/model-selection-guide",
|
||||
"review-kit/alignment/schema",
|
||||
"review-kit/alignment/scorecard",
|
||||
"review-kit/alignment/workflow",
|
||||
"review-kit/alignment/workplan-template",
|
||||
}
|
||||
|
||||
ALIGNMENT_REVIEW_REQUIRED_PHASES = {
|
||||
"intake",
|
||||
"surface-selection",
|
||||
"mapping",
|
||||
"scoring",
|
||||
"workplan-proposal",
|
||||
"canon-feedback",
|
||||
}
|
||||
|
||||
ALIGNMENT_REVIEW_SCORECARD_DIMENSIONS = {
|
||||
"fit",
|
||||
"gaps",
|
||||
"conflicts",
|
||||
"evidence-quality",
|
||||
"implementation-priority",
|
||||
"canon-pressure",
|
||||
"workplan-readiness",
|
||||
}
|
||||
|
||||
ALIGNMENT_REVIEW_REQUIRED_SURFACES = {
|
||||
"model/purpose-demand-extension",
|
||||
"pattern/intent-scope-purposes",
|
||||
"model/access-control",
|
||||
"model/organization",
|
||||
"model/governance",
|
||||
"model/security",
|
||||
"model/data",
|
||||
"model/landscape",
|
||||
"model/devsecops",
|
||||
"model/network",
|
||||
"model/observability",
|
||||
"model/task",
|
||||
"standard/tagging",
|
||||
"standard/caring",
|
||||
"profile/small-saas",
|
||||
"benchmark/caring/kubernetes-rbac",
|
||||
}
|
||||
|
||||
ALIGNMENT_REVIEW_TEMPLATE_MARKERS = {
|
||||
"## Current Fit",
|
||||
"## Target Alignment",
|
||||
"## Migration Steps",
|
||||
"## Validation",
|
||||
"## Open Questions",
|
||||
"## Canon Feedback",
|
||||
}
|
||||
|
||||
|
||||
def structural_checks(context: Any) -> dict[str, list[dict[str, Any]]]:
|
||||
errors: list[dict[str, Any]] = []
|
||||
@@ -314,6 +377,11 @@ def structural_checks(context: Any) -> dict[str, list[dict[str, Any]]]:
|
||||
context.infospace.artifacts,
|
||||
errors,
|
||||
)
|
||||
_check_alignment_review_kit_assets(
|
||||
context.infospace_root,
|
||||
context.infospace.artifacts,
|
||||
errors,
|
||||
)
|
||||
_check_optional_assets(context.infospace_root, warnings)
|
||||
|
||||
return {"errors": errors, "warnings": warnings}
|
||||
@@ -578,6 +646,7 @@ def _check_agent_assets(
|
||||
"agent/retrieval-index.json",
|
||||
"agent/templates/canon-interface-card.template.yaml",
|
||||
"agent/templates/consumer-brief.template.md",
|
||||
"agent/templates/consumer-alignment-workplan.template.md",
|
||||
"agent/consumer-briefs/user-engine.md",
|
||||
"agent/consumer-briefs/railiance-fabric.md",
|
||||
"agent/consumer-briefs/repo-scoping.md",
|
||||
@@ -1421,6 +1490,213 @@ def _check_caring_kubernetes_rbac_benchmark_assets(
|
||||
)
|
||||
|
||||
|
||||
def _check_alignment_review_kit_assets(
|
||||
infospace_root: Path,
|
||||
artifacts: list[Any],
|
||||
errors: list[dict[str, Any]],
|
||||
) -> None:
|
||||
artifact_ids = {artifact.id for artifact in artifacts}
|
||||
for artifact_id in sorted(ALIGNMENT_REVIEW_KIT_ARTIFACT_IDS - artifact_ids):
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_kit_artifact",
|
||||
"artifact_id": artifact_id,
|
||||
}
|
||||
)
|
||||
|
||||
kit_root = infospace_root / "agent" / "review-kit"
|
||||
manifest = _read_yaml(kit_root / "review-kit.yaml", errors)
|
||||
if isinstance(manifest, dict):
|
||||
components = manifest.get("components") or {}
|
||||
if not isinstance(components, dict):
|
||||
errors.append(
|
||||
{
|
||||
"code": "invalid_alignment_review_kit_components",
|
||||
"path": "infospace/agent/review-kit/review-kit.yaml",
|
||||
}
|
||||
)
|
||||
else:
|
||||
for component in (
|
||||
"workflow",
|
||||
"scorecard",
|
||||
"model_selection_guide",
|
||||
"schema",
|
||||
"consumer_workplan_template",
|
||||
):
|
||||
if not components.get(component):
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_kit_component",
|
||||
"component": component,
|
||||
}
|
||||
)
|
||||
outputs = set(manifest.get("required_outputs") or [])
|
||||
for output in (
|
||||
"repository_context",
|
||||
"selected_canon_surfaces",
|
||||
"mapping_findings",
|
||||
"scorecard",
|
||||
"recommended_workplans",
|
||||
"canon_feedback",
|
||||
):
|
||||
if output not in outputs:
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_required_output",
|
||||
"output": output,
|
||||
}
|
||||
)
|
||||
|
||||
workflow = _read_yaml(kit_root / "review-workflow.yaml", errors)
|
||||
if isinstance(workflow, dict):
|
||||
phases = workflow.get("phases") or []
|
||||
if not isinstance(phases, list):
|
||||
errors.append(
|
||||
{
|
||||
"code": "invalid_alignment_review_workflow_phases",
|
||||
"path": "infospace/agent/review-kit/review-workflow.yaml",
|
||||
}
|
||||
)
|
||||
else:
|
||||
phase_ids = {
|
||||
str(phase.get("id"))
|
||||
for phase in phases
|
||||
if isinstance(phase, dict) and phase.get("id")
|
||||
}
|
||||
for phase_id in sorted(ALIGNMENT_REVIEW_REQUIRED_PHASES - phase_ids):
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_workflow_phase",
|
||||
"phase": phase_id,
|
||||
}
|
||||
)
|
||||
for phase in phases:
|
||||
if not isinstance(phase, dict):
|
||||
continue
|
||||
if not phase.get("questions"):
|
||||
errors.append(
|
||||
{
|
||||
"code": "empty_alignment_review_phase_questions",
|
||||
"phase": phase.get("id"),
|
||||
}
|
||||
)
|
||||
if not phase.get("outputs"):
|
||||
errors.append(
|
||||
{
|
||||
"code": "empty_alignment_review_phase_outputs",
|
||||
"phase": phase.get("id"),
|
||||
}
|
||||
)
|
||||
|
||||
scorecard = _read_yaml(kit_root / "scorecard.yaml", errors)
|
||||
if isinstance(scorecard, dict):
|
||||
dimensions = scorecard.get("dimensions") or []
|
||||
if not isinstance(dimensions, list):
|
||||
errors.append(
|
||||
{
|
||||
"code": "invalid_alignment_review_scorecard_dimensions",
|
||||
"path": "infospace/agent/review-kit/scorecard.yaml",
|
||||
}
|
||||
)
|
||||
else:
|
||||
dimension_ids = {
|
||||
str(dimension.get("id"))
|
||||
for dimension in dimensions
|
||||
if isinstance(dimension, dict) and dimension.get("id")
|
||||
}
|
||||
for dimension in sorted(
|
||||
ALIGNMENT_REVIEW_SCORECARD_DIMENSIONS - dimension_ids
|
||||
):
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_scorecard_dimension",
|
||||
"dimension": dimension,
|
||||
}
|
||||
)
|
||||
|
||||
guide = _read_yaml(kit_root / "model-selection-guide.yaml", errors)
|
||||
if isinstance(guide, dict):
|
||||
surfaces = guide.get("surfaces") or []
|
||||
if not isinstance(surfaces, list):
|
||||
errors.append(
|
||||
{
|
||||
"code": "invalid_alignment_review_selection_surfaces",
|
||||
"path": "infospace/agent/review-kit/model-selection-guide.yaml",
|
||||
}
|
||||
)
|
||||
else:
|
||||
surface_ids = {
|
||||
str(surface.get("id"))
|
||||
for surface in surfaces
|
||||
if isinstance(surface, dict) and surface.get("id")
|
||||
}
|
||||
for surface_id in sorted(ALIGNMENT_REVIEW_REQUIRED_SURFACES - surface_ids):
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_selection_surface",
|
||||
"surface": surface_id,
|
||||
}
|
||||
)
|
||||
for surface in surfaces:
|
||||
if not isinstance(surface, dict):
|
||||
continue
|
||||
if not surface.get("use_when"):
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_surface_use_when",
|
||||
"surface": surface.get("id"),
|
||||
}
|
||||
)
|
||||
if not surface.get("review_questions"):
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_surface_questions",
|
||||
"surface": surface.get("id"),
|
||||
}
|
||||
)
|
||||
|
||||
schema = _read_yaml(infospace_root / "schemas" / "alignment-review.schema.yaml", errors)
|
||||
if isinstance(schema, dict):
|
||||
required_fields = set(schema.get("required") or [])
|
||||
for field in (
|
||||
"repository_context",
|
||||
"selected_canon_surfaces",
|
||||
"mapping_findings",
|
||||
"scorecard",
|
||||
"recommended_workplans",
|
||||
"canon_feedback",
|
||||
):
|
||||
if field not in required_fields:
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_schema_required_field",
|
||||
"field": field,
|
||||
}
|
||||
)
|
||||
|
||||
template_path = (
|
||||
infospace_root / "agent" / "templates" / "consumer-alignment-workplan.template.md"
|
||||
)
|
||||
try:
|
||||
template = template_path.read_text(encoding="utf-8")
|
||||
except FileNotFoundError:
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_workplan_template",
|
||||
"path": "infospace/agent/templates/consumer-alignment-workplan.template.md",
|
||||
}
|
||||
)
|
||||
else:
|
||||
for marker in sorted(ALIGNMENT_REVIEW_TEMPLATE_MARKERS):
|
||||
if marker not in template:
|
||||
errors.append(
|
||||
{
|
||||
"code": "missing_alignment_review_template_marker",
|
||||
"marker": marker,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _artifact_paths_by_path(
|
||||
infospace_root: Path,
|
||||
errors: list[dict[str, Any]],
|
||||
|
||||
Reference in New Issue
Block a user