Noetrail_Reference_Prototype_v1.0/
├── noetrail_ref.py
├── schemas/
│ ├── epistemic-state.schema.json
│ ├── epistemic-policy.schema.json
│ ├── challenge-profile.schema.json
│ ├── decision-record.schema.json
│ └── registry-index.schema.json
├── registry.json
├── example-policy.json
├── example-challenge.json
├── example-decision.json
└── README.md
import json
import hashlib
import sys
from pathlib import Path
try:
import jsonschema
except ImportError:
print("Missing dependency: jsonschema")
print("Install with: pip install jsonschema")
sys.exit(1)
BASE_DIR = Path(__file__).resolve().parent
SCHEMA_DIR = BASE_DIR / "schemas"
SCHEMA_MAP = {
"EpistemicState": "epistemic-state.schema.json",
"EpistemicPolicy": "epistemic-policy.schema.json",
"ChallengeProfile": "challenge-profile.schema.json",
"DecisionRecord": "decision-record.schema.json",
"NoetrailRegistry": "registry-index.schema.json",
}
def load_json(path):
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
def save_json(path, data):
with open(path, "w", encoding="utf-8") as f:
json.dump(
data,
f,
ensure_ascii=False,
indent=2
)
def canonical_json(obj):
return json.dumps(
obj,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":")
)
def sha256_text(text):
return hashlib.sha256(
text.encode("utf-8")
).hexdigest()
def file_sha256(path):
h = hashlib.sha256()
with open(path, "rb") as f:
while True:
block = f.read(65536)
if not block:
break
h.update(block)
return h.hexdigest()
def semantic_sha256(path):
obj = load_json(path)
if isinstance(obj, dict):
obj = dict(obj)
obj.pop("artifact_hash", None)
return sha256_text(canonical_json(obj))
def structural_validate(obj):
object_type = obj.get("type")
if object_type not in SCHEMA_MAP:
return {
"result": "INVALID",
"stage": "structural",
"errors": [
{
"code": "NTRL-E101",
"message": f"Unknown object type: {object_type}"
}
]
}
schema_path = SCHEMA_DIR / SCHEMA_MAP[object_type]
schema = load_json(schema_path)
validator = jsonschema.Draft202012Validator(schema)
errors = sorted(
validator.iter_errors(obj),
key=lambda e: list(e.path)
)
if errors:
return {
"result": "INVALID",
"stage": "structural",
"errors": [
{
"code": "NTRL-E101",
"field": ".".join(str(p) for p in e.path),
"message": e.message
}
for e in errors
]
}
return {
"result": "VALID",
"stage": "structural",
"errors": []
}
def validate_action_class(action):
core_actions = {
"experiment",
"direct_replication",
"conceptual_replication",
"adversarial_test",
"measurement_audit",
"causal_identification",
"reanalysis",
"boundary_search",
"model_criticism",
"model_generation",
"evidence_synthesis",
"random_exploration",
"stop_defer",
}
if action in core_actions:
return True
# Custom actions must be namespaced.
if ":" in action:
return True
return False
def semantic_validate_policy(obj):
errors = []
output_contract = obj.get("output_contract", {})
action_class = output_contract.get("action_class")
actions = (
action_class
if isinstance(action_class, list)
else [action_class]
)
for action in actions:
if action is None:
continue
if not validate_action_class(action):
errors.append({
"code": "NTRL-E302",
"field": "output_contract.action_class",
"message": f"Unknown non-namespaced action class: {action}"
})
exploration = obj.get("protected_exploration")
if isinstance(exploration, dict):
value = exploration.get("minimum_random_fraction")
if value is not None:
if not isinstance(value, (int, float)) or not 0 <= value <= 1:
errors.append({
"code": "NTRL-E303",
"field": "protected_exploration.minimum_random_fraction",
"message": "minimum_random_fraction must be between 0 and 1"
})
return errors
def semantic_validate_decision(decision, challenge=None):
errors = []
if challenge is None:
return errors
if (
decision.get("challenge_profile_id")
!= challenge.get("id")
):
errors.append({
"code": "NTRL-E304",
"field": "challenge_profile_id",
"message": "DecisionRecord does not reference the supplied ChallengeProfile"
})
decision_lock = decision.get("challenge_lock_hash")
challenge_lock = challenge.get("lock_hash")
if challenge.get("locked") is True:
if decision_lock != challenge_lock:
errors.append({
"code": "NTRL-E305",
"field": "challenge_lock_hash",
"message": "DecisionRecord lock hash does not match ChallengeProfile"
})
if decision.get("decision") == "promote":
if challenge.get("prospective") is not True:
errors.append({
"code": "NTRL-E301",
"field": "decision",
"message": "Retrospective challenge cannot produce a conformant promotion"
})
if challenge.get("locked") is not True:
errors.append({
"code": "NTRL-E306",
"field": "decision",
"message": "Unlocked challenge cannot produce a conformant promotion"
})
gate_results = decision.get("gate_results", [])
failed = [
g for g in gate_results
if g.get("passed") is False
]
if failed:
errors.append({
"code": "NTRL-E307",
"field": "gate_results",
"message": "Promotion attempted despite one or more failed gates"
})
return errors
def semantic_validate(obj, challenge=None):
object_type = obj.get("type")
errors = []
if object_type == "EpistemicPolicy":
errors.extend(
semantic_validate_policy(obj)
)
elif object_type == "DecisionRecord":
errors.extend(
semantic_validate_decision(
obj,
challenge=challenge
)
)
if errors:
return {
"result": "INVALID",
"stage": "semantic",
"errors": errors
}
return {
"result": "VALID",
"stage": "semantic",
"errors": []
}
def validate(path, challenge_path=None):
obj = load_json(path)
structural = structural_validate(obj)
if structural["result"] != "VALID":
return {
"standard": "Noetrail v1.0",
"object_type": obj.get("type"),
**structural
}
challenge = None
if challenge_path:
challenge = load_json(challenge_path)
semantic = semantic_validate(
obj,
challenge=challenge
)
return {
"standard": "Noetrail v1.0",
"object_type": obj.get("type"),
**semantic
}
def registry_find(registry, policy_id, version):
for entry in registry.get("entries", []):
if (
entry.get("policy_id") == policy_id
and entry.get("version") == version
):
return entry
return None
def registry_add(registry_path, policy_path, write=False):
registry = load_json(registry_path)
policy = load_json(policy_path)
validation = validate(policy_path)
if validation["result"] != "VALID":
return {
"result": "REJECT",
"reason": "Policy is not valid",
"validation": validation
}
policy_id = policy["id"]
version = policy["version"]
artifact_hash = policy["artifact_hash"]
existing = registry_find(
registry,
policy_id,
version
)
if existing:
if existing.get("artifact_hash") != artifact_hash:
return {
"result": "REJECT",
"code": "NTRL-E201",
"message": "Duplicate policy identity with different artifact hash"
}
return {
"result": "ALREADY_REGISTERED",
"policy_id": policy_id,
"version": version
}
entry = {
"policy_id": policy_id,
"version": version,
"title": policy.get("title", ""),
"status": "example",
"artifact_hash": artifact_hash,
"schema_conformance": "Noetrail v1.0"
}
registry["entries"].append(entry)
if write:
save_json(
registry_path,
registry
)
return {
"result": "ACCEPT",
"written": write,
"entry": entry
}
def registry_list(registry_path):
registry = load_json(registry_path)
return registry.get("entries", [])
def registry_inspect(registry_path, policy_id, version):
registry = load_json(registry_path)
result = registry_find(
registry,
policy_id,
version
)
if result is None:
return {
"result": "NOT_FOUND"
}
return {
"result": "FOUND",
"entry": result
}
def print_json(data):
print(
json.dumps(
data,
ensure_ascii=False,
indent=2
)
)
def usage():
print("""
Noetrail Reference Prototype v1.0
Commands:
validate FILE
validate FILE --challenge CHALLENGE_FILE
hash FILE
hash FILE --semantic
registry-list REGISTRY_FILE
registry-inspect REGISTRY_FILE POLICY_ID VERSION
registry-add REGISTRY_FILE POLICY_FILE
registry-add REGISTRY_FILE POLICY_FILE --write
""")
def main():
args = sys.argv[1:]
if not args:
usage()
sys.exit(0)
command = args[0]
if command == "validate":
if len(args) < 2:
usage()
sys.exit(1)
path = args[1]
challenge_path = None
if "--challenge" in args:
i = args.index("--challenge")
challenge_path = args[i + 1]
print_json(
validate(
path,
challenge_path=challenge_path
)
)
elif command == "hash":
if len(args) < 2:
usage()
sys.exit(1)
path = args[1]
if "--semantic" in args:
result = semantic_sha256(path)
else:
result = file_sha256(path)
print(result)
elif command == "registry-list":
print_json(
registry_list(args[1])
)
elif command == "registry-inspect":
if len(args) < 4:
usage()
sys.exit(1)
print_json(
registry_inspect(
args[1],
args[2],
args[3]
)
)
elif command == "registry-add":
if len(args) < 3:
usage()
sys.exit(1)
write = "--write" in args
print_json(
registry_add(
args[1],
args[2],
write=write
)
)
else:
usage()
sys.exit(1)
if __name__ == "__main__":
main()
Спочатку:
pip install jsonschema
Потім:
python noetrail_ref.py validate example-policy.json
або:
python noetrail_ref.py validate example-decision.json --challenge example-challenge.json
Hash:
python noetrail_ref.py hash example-policy.json
Canonical semantic hash:
python noetrail_ref.py hash example-policy.json --semantic
Registry:
python noetrail_ref.py registry-list registry.json
{
"type": "EpistemicPolicy",
"id": "urn:noetrail:policy:measurement-first",
"version": "1.0.0",
"title": "Measurement First",
"scope": "Psychological research with unresolved measurement uncertainty",
"input_profile": {
"profile": "psychology-measurement"
},
"output_contract": {
"action_class": "measurement_audit",
"uncertainty_required": true,
"rationale_required": true
},
"protected_exploration": null,
"implementation": {
"kind": "reference-example"
},
"artifact_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"license": "CC0-1.0",
"provenance": [
{
"role": "example"
}
]
}
{
"type": "ChallengeProfile",
"id": "urn:noetrail:challenge:example-001",
"incumbent": {
"policy_id": "urn:noetrail:policy:measurement-first",
"version": "1.0.0"
},
"challengers": [
{
"policy_id": "urn:noetrail:policy:replication-first",
"version": "1.0.0"
}
],
"benchmark_refs": [
{
"id": "benchmark-example"
}
],
"metrics": [
"error_detection_rate"
],
"gates": [
{
"id": "g1",
"metric": "error_detection_advantage",
"op": ">=",
"value": 0.05
}
],
"development_exclusions": [],
"exploration_constraints": null,
"seed_protocol": null,
"prospective": false,
"locked": false,
"lock_hash": "NOT_LOCKED",
"notes": "Retrospective example"
}
{
"type": "DecisionRecord",
"id": "urn:noetrail:decision:example-001",
"challenge_profile_id": "urn:noetrail:challenge:example-001",
"challenge_lock_hash": "NONE",
"results": {
"incumbent": 0.61,
"challenger": 0.68
},
"gate_results": [],
"decision": "inconclusive",
"selected_policy": null,
"failures": [
"No prospective locked promotion contract existed."
],
"artifact_hashes": {},
"provenance": [
{
"status": "retrospective"
}
],
"timestamp": "2026-09-26T20:00:00Z"
}
{
"type": "NoetrailRegistry",
"version": "1.0.0",
"entries": []
}