scripts.factory_anchors
Reference › scripts › factory_anchors
The command-line interface for the SPEC-033 semantic anchor registry (B15a; ADR-0012, ADR-0013 and ADR-0016). It uses the anchor evaluation and gate code in evaluation and gate; the factory narrative describes the subsystem. No module or test imports it.
Invocation: main takes a subcommand and dispatches to its handler. The subcommands are propose (add an anchor proposal), import-dor (import anchors from a definition-of-ready source), ratify, supersede, list, evaluate and fast-path. evaluate loads an evidence file (_load_evidence) and runs the default evaluators (_default_evaluators). fast-path is handled by _cmd_fast_path; compare the separate factory_fastpath script. Each handler returns the process exit code, and every subcommand has its own parser builder (_add_propose_parser and its siblings).
At a glance
| Source | scripts/factory_anchors.py |
| Lines of code | 329 |
| Classes | 0 |
| Functions | 18 |
| Imports (internal) | orchestrata_ultimate.factory.anchors.evaluation, orchestrata_ultimate.factory.anchors.gate, orchestrata_ultimate.factory.anchors.intake, orchestrata_ultimate.factory.anchors.models, orchestrata_ultimate.factory.anchors.store |
| Imported by | none |
| Tests that import it | none |
Class diagram
No classes; see Functions.
Dependency diagram
API
Functions
| Function | Signature | Summary |
|---|---|---|
_default_evaluators |
_default_evaluators() -> list[AnchorEvaluator] |
The three built-in evaluators (one per :class:AnchorClass). |
_load_evidence |
_load_evidence(evidence_path: Path) -> AnchorEvidence |
Load an AnchorEvidence from a JSON file. |
_cmd_propose |
_cmd_propose(args: argparse.Namespace) -> int |
|
_cmd_import_dor |
_cmd_import_dor(args: argparse.Namespace) -> int |
|
_cmd_ratify |
_cmd_ratify(args: argparse.Namespace) -> int |
|
_cmd_supersede |
_cmd_supersede(args: argparse.Namespace) -> int |
|
_cmd_list |
_cmd_list(args: argparse.Namespace) -> int |
|
_cmd_evaluate |
_cmd_evaluate(args: argparse.Namespace) -> int |
|
_cmd_fast_path |
_cmd_fast_path(args: argparse.Namespace) -> int |
|
_add_propose_parser |
_add_propose_parser(sub: argparse._SubParsersAction) -> None |
|
_add_import_dor_parser |
_add_import_dor_parser(sub: argparse._SubParsersAction) -> None |
|
_add_ratify_parser |
_add_ratify_parser(sub: argparse._SubParsersAction) -> None |
|
_add_supersede_parser |
_add_supersede_parser(sub: argparse._SubParsersAction) -> None |
|
_add_list_parser |
_add_list_parser(sub: argparse._SubParsersAction) -> None |
|
_add_evaluate_parser |
_add_evaluate_parser(sub: argparse._SubParsersAction) -> None |
|
_add_fast_path_parser |
_add_fast_path_parser(sub: argparse._SubParsersAction) -> None |
|
_build_parser |
_build_parser() -> argparse.ArgumentParser |
|
main |
main(argv: list[str] | None = None) -> int |
Parse argv and dispatch to the matching subcommand handler. |
Source
#!/usr/bin/env python3
"""CLI for the SPEC-033 semantic anchor registry (B15a, ADR-0012/0013/0016).
Subcommands
-----------
propose Propose a new anchor (status is always forced to PROPOSED).
import-dor Import B23 DoR anchor candidates as PROPOSED EXAMPLE anchors.
ratify PROPOSED -> RATIFIED (the human act -- ADR-0013).
supersede RATIFIED -> SUPERSEDED, replaced by another anchor (the only
edit path for a ratified anchor -- ADR-0013).
list Print every anchor (optionally filtered), a per-class count
line, and the human-ratification-pending count (ADR-0016's
price rule made visible).
evaluate Evaluate a requirement's RATIFIED anchors against observed
evidence (B15b, pure comparison, no code execution).
fast-path The ADR-0023 fast-path eligibility gate: satisfied AND
unchanged anchors, or it is blocked (B15b).
Examples
--------
python scripts/factory_anchors.py propose --registry anchors.json \\
--requirement REQ-033-C5 --class example --statement "..." \\
--source "authored:mohamed"
python scripts/factory_anchors.py import-dor --registry anchors.json \\
--from candidates.json
python scripts/factory_anchors.py ratify --registry anchors.json \\
--id ANC-xxxxxxxxxxxx --by mohamed
python scripts/factory_anchors.py list --registry anchors.json
python scripts/factory_anchors.py evaluate --registry anchors.json \\
--requirement REQ-033-C5 --evidence evidence.json
python scripts/factory_anchors.py fast-path --registry anchors.json \\
--requirement REQ-033-C5 --evidence evidence.json \\
--changed ANC-xxxxxxxxxxxx
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
# Ensure repo src is on path when run directly (mirrors kg_schema.py /
# factory_dor_procedure.py / run_ast_pipeline.py).
_repo_src = Path(__file__).resolve().parent.parent / "src"
if str(_repo_src) not in sys.path:
sys.path.insert(0, str(_repo_src))
from orchestrata_ultimate.factory.anchors.evaluation import ( # noqa: E402
AnchorEvaluator,
AnchorEvidence,
ExampleEvaluator,
OracleEvaluator,
PropertyEvaluator,
Satisfaction,
evaluate_all,
)
from orchestrata_ultimate.factory.anchors.gate import fast_path_gate # noqa: E402
from orchestrata_ultimate.factory.anchors.intake import ( # noqa: E402
import_dor_candidates,
)
from orchestrata_ultimate.factory.anchors.models import ( # noqa: E402
Anchor,
AnchorClass,
AnchorStatus,
)
from orchestrata_ultimate.factory.anchors.store import AnchorRegistry # noqa: E402
def _default_evaluators() -> list[AnchorEvaluator]:
"""The three built-in evaluators (one per :class:`AnchorClass`)."""
return [ExampleEvaluator(), PropertyEvaluator(), OracleEvaluator()]
def _load_evidence(evidence_path: Path) -> AnchorEvidence:
"""Load an ``AnchorEvidence`` from a JSON file.
Expected shape: ``{"observed_outputs": {...}, "differential": {...}}``
(both optional, default to ``{}``).
"""
with open(evidence_path, encoding="utf-8") as f:
data = json.load(f)
return AnchorEvidence(
observed_outputs=data.get("observed_outputs", {}),
differential=data.get("differential", {}),
)
def _cmd_propose(args: argparse.Namespace) -> int:
registry = AnchorRegistry(Path(args.registry))
try:
anchor = Anchor.new(
requirement_id=args.requirement,
klass=AnchorClass(args.klass.lower()),
statement=args.statement,
boundary=args.boundary or "",
source=args.source or "",
)
proposed = registry.propose(anchor)
except ValueError as exc:
print(f"error: {exc}")
return 1
print(proposed.anchor_id)
return 0
def _cmd_import_dor(args: argparse.Namespace) -> int:
registry = AnchorRegistry(Path(args.registry))
try:
proposed = import_dor_candidates(Path(args.from_path), registry)
except (ValueError, OSError) as exc:
print(f"error: {exc}")
return 1
for anchor in proposed:
print(anchor.anchor_id)
print(f"imported {len(proposed)} anchor candidate(s)")
return 0
def _cmd_ratify(args: argparse.Namespace) -> int:
registry = AnchorRegistry(Path(args.registry))
try:
anchor = registry.ratify(args.id, args.by)
except ValueError as exc:
print(f"error: {exc}")
return 1
print(anchor.anchor_id)
return 0
def _cmd_supersede(args: argparse.Namespace) -> int:
registry = AnchorRegistry(Path(args.registry))
try:
anchor = registry.supersede(args.id, args.replacement, args.by)
except ValueError as exc:
print(f"error: {exc}")
return 1
print(anchor.anchor_id)
return 0
def _cmd_list(args: argparse.Namespace) -> int:
registry = AnchorRegistry(Path(args.registry))
status_filter = AnchorStatus(args.status.lower()) if args.status else None
anchors = registry.anchors(requirement_id=args.requirement, status=status_filter)
for anchor in anchors:
print(
f"{anchor.anchor_id} {anchor.status.value} klass={anchor.klass.value} "
f"requirement={anchor.requirement_id} source={anchor.source!r} "
f"statement={anchor.statement!r}"
)
per_class: dict[str, int] = {}
for anchor in anchors:
per_class[anchor.klass.value] = per_class.get(anchor.klass.value, 0) + 1
counts = ", ".join(f"{klass}={count}" for klass, count in sorted(per_class.items()))
print(f"by-class: {counts or '(none)'}")
pending = sum(1 for a in anchors if a.status == AnchorStatus.PROPOSED)
print(f"human-ratification pending: {pending} proposed anchors")
return 0
def _cmd_evaluate(args: argparse.Namespace) -> int:
registry = AnchorRegistry(Path(args.registry))
try:
evidence = _load_evidence(Path(args.evidence))
except (OSError, ValueError) as exc:
print(f"error: {exc}")
return 1
anchors = registry.anchors(
requirement_id=args.requirement, status=AnchorStatus.RATIFIED
)
results = evaluate_all(anchors, evidence, _default_evaluators())
for result in results:
print(
f"{result.anchor_id} {result.satisfaction.value} "
f"klass={result.klass.value} detail={result.detail!r}"
)
if not results:
print(f"no RATIFIED anchors for requirement {args.requirement}")
unsatisfied = [r for r in results if r.satisfaction == Satisfaction.UNSATISFIED]
return 1 if unsatisfied else 0
def _cmd_fast_path(args: argparse.Namespace) -> int:
registry = AnchorRegistry(Path(args.registry))
try:
evidence = _load_evidence(Path(args.evidence))
except (OSError, ValueError) as exc:
print(f"error: {exc}")
return 1
changed_anchor_ids = set(args.changed or [])
verdict = fast_path_gate(
[args.requirement],
registry,
evidence,
_default_evaluators(),
changed_anchor_ids=changed_anchor_ids,
)
for result in verdict.results:
print(
f"{result.anchor_id} {result.satisfaction.value} "
f"klass={result.klass.value} detail={result.detail!r}"
)
if verdict.fast_path_eligible:
print("fast-path: ELIGIBLE")
return 0
reasons = []
if verdict.blocking:
reasons.append(f"blocking anchors: {', '.join(verdict.blocking)}")
if verdict.edited_anchor_ids:
reasons.append(f"edited anchors: {', '.join(verdict.edited_anchor_ids)}")
print(f"fast-path: BLOCKED ({'; '.join(reasons) or 'no ratified anchors'})")
return 1
def _add_propose_parser(sub: argparse._SubParsersAction) -> None:
propose_p = sub.add_parser(
"propose", help="Propose a new anchor (always PROPOSED)."
)
propose_p.add_argument("--registry", required=True)
propose_p.add_argument("--requirement", required=True)
propose_p.add_argument(
"--class",
dest="klass",
required=True,
choices=[c.value for c in AnchorClass],
)
propose_p.add_argument("--statement", required=True)
propose_p.add_argument("--boundary", default="")
propose_p.add_argument("--source", default="")
def _add_import_dor_parser(sub: argparse._SubParsersAction) -> None:
import_p = sub.add_parser("import-dor", help="Import B23 DoR anchor candidates.")
import_p.add_argument("--registry", required=True)
import_p.add_argument("--from", dest="from_path", required=True)
def _add_ratify_parser(sub: argparse._SubParsersAction) -> None:
ratify_p = sub.add_parser(
"ratify", help="Ratify a PROPOSED anchor (human act -- ADR-0013)."
)
ratify_p.add_argument("--registry", required=True)
ratify_p.add_argument("--id", required=True)
ratify_p.add_argument("--by", required=True)
def _add_supersede_parser(sub: argparse._SubParsersAction) -> None:
supersede_p = sub.add_parser(
"supersede",
help="Supersede a RATIFIED anchor (the only edit path -- ADR-0013).",
)
supersede_p.add_argument("--registry", required=True)
supersede_p.add_argument("--id", required=True)
supersede_p.add_argument("--replacement", required=True)
supersede_p.add_argument("--by", required=True)
def _add_list_parser(sub: argparse._SubParsersAction) -> None:
list_p = sub.add_parser(
"list", help="Print anchors + per-class + pending-ratification counts."
)
list_p.add_argument("--registry", required=True)
list_p.add_argument("--requirement", default=None)
list_p.add_argument("--status", default=None)
def _add_evaluate_parser(sub: argparse._SubParsersAction) -> None:
evaluate_p = sub.add_parser(
"evaluate",
help=(
"Evaluate a requirement's RATIFIED anchors against observed "
"evidence (B15b)."
),
)
evaluate_p.add_argument("--registry", required=True)
evaluate_p.add_argument("--requirement", required=True)
evaluate_p.add_argument("--evidence", required=True)
def _add_fast_path_parser(sub: argparse._SubParsersAction) -> None:
fast_path_p = sub.add_parser(
"fast-path",
help="ADR-0023 fast-path eligibility gate: satisfied AND unchanged (B15b).",
)
fast_path_p.add_argument("--registry", required=True)
fast_path_p.add_argument("--requirement", required=True)
fast_path_p.add_argument("--evidence", required=True)
fast_path_p.add_argument(
"--changed", nargs="*", default=[], metavar="ANCHOR_ID", dest="changed"
)
def _build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="factory_anchors",
description="SPEC-033 semantic anchor registry CLI (B15a/B15b).",
)
sub = parser.add_subparsers(dest="command", required=True)
_add_propose_parser(sub)
_add_import_dor_parser(sub)
_add_ratify_parser(sub)
_add_supersede_parser(sub)
_add_list_parser(sub)
_add_evaluate_parser(sub)
_add_fast_path_parser(sub)
return parser
def main(argv: list[str] | None = None) -> int:
"""Parse ``argv`` and dispatch to the matching subcommand handler."""
parser = _build_parser()
args = parser.parse_args(argv)
dispatch = {
"propose": _cmd_propose,
"import-dor": _cmd_import_dor,
"ratify": _cmd_ratify,
"supersede": _cmd_supersede,
"list": _cmd_list,
"evaluate": _cmd_evaluate,
"fast-path": _cmd_fast_path,
}
handler = dispatch[args.command]
return handler(args)
if __name__ == "__main__":
sys.exit(main())