feat: add Guanghu persona continuity skill kernel
Part 3/4 of the recovered Fifth Domain upgrade. Applies the persona continuity skill guard from local source commit 18dfdfd without rewriting remote history.
This commit is contained in:
parent
8485822da6
commit
c5be48e6a1
16 changed files with 639 additions and 6 deletions
|
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Compile experience receipts into non-enforcing candidate skill rules."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
DEFAULT_RECEIPTS = Path(__file__).resolve().parents[1] / "references" / "experience-receipts"
|
||||
REQUIRED_FIELDS = {
|
||||
"schema",
|
||||
"receipt_id",
|
||||
"intent",
|
||||
"scope",
|
||||
"input",
|
||||
"evidence",
|
||||
"decision",
|
||||
"action",
|
||||
"observed_result",
|
||||
"correction",
|
||||
"invariant_id",
|
||||
"invariant",
|
||||
"verification",
|
||||
"receipt_path",
|
||||
"promotion_state",
|
||||
"recorded_at",
|
||||
}
|
||||
|
||||
|
||||
def load_receipts(directory: Path = DEFAULT_RECEIPTS) -> list[dict]:
|
||||
receipts = []
|
||||
for path in sorted(directory.glob("*.json")):
|
||||
with path.open(encoding="utf-8") as handle:
|
||||
receipt = json.load(handle)
|
||||
missing = REQUIRED_FIELDS.difference(receipt)
|
||||
if missing:
|
||||
raise ValueError(f"{path.name} missing fields: {sorted(missing)}")
|
||||
if receipt["schema"] != "guanghu.ops-experience-receipt/v1":
|
||||
raise ValueError(f"{path.name} has unsupported schema")
|
||||
if not receipt["evidence"] or not receipt["verification"]:
|
||||
raise ValueError(f"{path.name} must contain evidence and verification")
|
||||
receipts.append(receipt)
|
||||
return receipts
|
||||
|
||||
|
||||
def compile_candidates(receipts: list[dict]) -> dict:
|
||||
grouped: dict[str, list[dict]] = defaultdict(list)
|
||||
for receipt in receipts:
|
||||
grouped[receipt["invariant_id"]].append(receipt)
|
||||
|
||||
candidates = []
|
||||
for invariant_id, items in sorted(grouped.items()):
|
||||
invariant_texts = {item["invariant"] for item in items}
|
||||
if len(invariant_texts) != 1:
|
||||
raise ValueError(f"{invariant_id} has conflicting invariant text")
|
||||
candidates.append(
|
||||
{
|
||||
"candidate_id": f"CANDIDATE-{invariant_id}",
|
||||
"invariant_id": invariant_id,
|
||||
"invariant": items[0]["invariant"],
|
||||
"scopes": sorted({item["scope"] for item in items}),
|
||||
"source_receipts": [item["receipt_id"] for item in items],
|
||||
"corrections": sorted({item["correction"] for item in items}),
|
||||
"verification": sorted({step for item in items for step in item["verification"]}),
|
||||
"enforcement_level": "CANDIDATE_ONLY",
|
||||
"hard_block_allowed": False,
|
||||
"promotion_requirements": [
|
||||
"current fact-source review",
|
||||
"applicability and counterexample review",
|
||||
"automated or reproducible tests",
|
||||
"registry update with recovery route",
|
||||
"explicit governance approval for hard enforcement",
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"schema": "guanghu.emergent-skill-candidates/v1",
|
||||
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||
"source_receipt_count": len(receipts),
|
||||
"candidate_count": len(candidates),
|
||||
"enforcement_policy": "Compilation never promotes or enforces a rule.",
|
||||
"candidates": candidates,
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--receipts", type=Path, default=DEFAULT_RECEIPTS)
|
||||
parser.add_argument("--output", type=Path)
|
||||
args = parser.parse_args()
|
||||
result = compile_candidates(load_receipts(args.receipts))
|
||||
payload = json.dumps(result, ensure_ascii=False, indent=2) + "\n"
|
||||
if args.output:
|
||||
args.output.write_text(payload, encoding="utf-8")
|
||||
else:
|
||||
print(payload, end="")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Reference in a new issue