From cbc0f625d945b624dbed1e5af07c8bc59cd99ef0 Mon Sep 17 00:00:00 2001 From: epi13 Date: Sat, 8 Aug 2026 10:42:55 -0800 Subject: [PATCH] organize versioned RAVEL artifacts --- .gitignore | 14 + Makefile | 281 +++++++----------- README.md | 2 +- .../ARCHITECTURE_GAPS.md | 0 docs/EVIDENCE_GUIDE.md | 34 ++- docs/HISTORICAL_RAVEL_README.md | 57 ++-- MIGRATION.md => docs/MIGRATION.md | 0 .../MIGRATION_ORIGIN.md | 0 docs/PROJECT_MAP.md | 170 +++-------- docs/README.md | 12 +- docs/VERSION_HISTORY.md | 71 +++-- .../0.4/RAVEL_0_4_CONTRACT.md | 0 .../0.4/RAVEL_0_4_RESULTS.md | 0 .../0.4/RAVEL_0_4_SCOPE.md | 0 ravel_versions/0.4/path_compat.py | 64 ++++ .../0.4/ravel-0.4-assurance-case.json | 0 .../0.4/ravel-0.4-limitations.md | 0 .../0.4/ravel-0.4-negative-evidence.json | 0 .../0.4/ravel-0.4-preregistration.json | 0 .../0.4/ravel-0.4-raw-observations.json | 0 .../0.4/ravel-0.4-runtime-observations.json | 0 .../0.4/ravel-0.4-source-manifest-spec.json | 0 .../0.4/ravel-0.4-source-manifest.json | 0 .../0.4/ravel-0.4-threat-model.json | 0 .../0.4/ravel-0.4-trial-evidence.json | 0 ravel_0_4.c => ravel_versions/0.4/ravel_0_4.c | 0 ravel_versions/0.4/run_evidence.py | 36 +++ ravel_versions/0.4/run_source_digest.py | 21 ++ ravel_versions/0.5/Makefile | 218 ++++++++++++++ .../0.5/RAVEL_0_5_CONTRACT.md | 0 .../0.5/RAVEL_0_5_POSTMORTEM.md | 0 .../0.5/RAVEL_0_5_RESULTS.md | 0 .../0.5/RAVEL_0_5_SCOPE.md | 0 .../0.5/ravel-0.5-assurance-case.json | 0 .../0.5/ravel-0.5-development-corpus.json | 0 .../0.5/ravel-0.5-limitations.md | 0 .../0.5/ravel-0.5-negative-evidence.json | 0 .../0.5/ravel-0.5-preregistration.json | 0 .../0.5/ravel-0.5-raw-observations.json | 0 .../0.5/ravel-0.5-runtime-observations.json | 0 ...vel-0.5-source-and-execution-manifest.json | 0 .../0.5/ravel-0.5-source-manifest-spec.json | 0 .../0.5/ravel-0.5-threat-model.json | 0 .../0.5/ravel-0.5-trial-evidence.json | 0 ravel_0_5.c => ravel_versions/0.5/ravel_0_5.c | 0 ravel_versions/0.5/run_evidence.py | 144 +++++++++ .../0.6/RAVEL_0_6_NEXT_STEPS.md | 0 .../0.6/RAVEL_0_6_PREREGISTRATION.md | 0 .../0.6/RAVEL_0_6_SCOPE.md | 0 .../0.6/ravel-0.6-development-record.json | 0 .../0.6/ravel-0.6-limitations.md | 0 .../0.6/ravel-0.6-preregistration.json | 0 .../0.6/ravel-0.6-preregistration.schema.json | 0 .../0.6/ravel-0.6-threat-model.json | 0 .../baseline/CONTRACT.md | 0 .../baseline/evidence.json | 0 ravel.c => ravel_versions/baseline/ravel.c | 0 .../training/TRAINING_CONTRACT.md | 0 .../training/ravel_train.c | 0 .../training/training-assurance-case.json | 0 .../training/training-evidence.json | 0 .../training/training-preregistration.json | 0 .../training/training-threat-model.json | 0 .../unified/UNIFIED_CONTRACT.md | 0 .../unified/ravel_unified.c | 0 .../unified/ravel_unified}/00_core.inc | 0 .../unified/ravel_unified}/10_route.inc | 0 .../unified/ravel_unified}/20_train.inc | 0 .../unified/ravel_unified}/30_eval.inc | 0 .../unified/unified-assurance-case.json | 0 .../unified/unified-evidence.json | 0 .../unified/unified-preregistration.json | 0 .../unified/unified-threat-model.json | 0 tools/README.md | 9 +- .../ravel_0_5_evaluator.cpython-314.pyc | Bin 54893 -> 0 bytes .../ravel_0_5_source_digest.cpython-314.pyc | Bin 16403 -> 0 bytes .../ravel_source_digest.cpython-314.pyc | Bin 13943 -> 0 bytes tools/ravel_0_6_seed_candidate.py | 2 +- 78 files changed, 754 insertions(+), 381 deletions(-) create mode 100644 .gitignore rename ARCHITECTURE_GAPS.md => docs/ARCHITECTURE_GAPS.md (100%) rename MIGRATION.md => docs/MIGRATION.md (100%) rename MIGRATION_ORIGIN.md => docs/MIGRATION_ORIGIN.md (100%) rename RAVEL_0_4_CONTRACT.md => ravel_versions/0.4/RAVEL_0_4_CONTRACT.md (100%) rename RAVEL_0_4_RESULTS.md => ravel_versions/0.4/RAVEL_0_4_RESULTS.md (100%) rename RAVEL_0_4_SCOPE.md => ravel_versions/0.4/RAVEL_0_4_SCOPE.md (100%) create mode 100644 ravel_versions/0.4/path_compat.py rename ravel-0.4-assurance-case.json => ravel_versions/0.4/ravel-0.4-assurance-case.json (100%) rename ravel-0.4-limitations.md => ravel_versions/0.4/ravel-0.4-limitations.md (100%) rename ravel-0.4-negative-evidence.json => ravel_versions/0.4/ravel-0.4-negative-evidence.json (100%) rename ravel-0.4-preregistration.json => ravel_versions/0.4/ravel-0.4-preregistration.json (100%) rename ravel-0.4-raw-observations.json => ravel_versions/0.4/ravel-0.4-raw-observations.json (100%) rename ravel-0.4-runtime-observations.json => ravel_versions/0.4/ravel-0.4-runtime-observations.json (100%) rename ravel-0.4-source-manifest-spec.json => ravel_versions/0.4/ravel-0.4-source-manifest-spec.json (100%) rename ravel-0.4-source-manifest.json => ravel_versions/0.4/ravel-0.4-source-manifest.json (100%) rename ravel-0.4-threat-model.json => ravel_versions/0.4/ravel-0.4-threat-model.json (100%) rename ravel-0.4-trial-evidence.json => ravel_versions/0.4/ravel-0.4-trial-evidence.json (100%) rename ravel_0_4.c => ravel_versions/0.4/ravel_0_4.c (100%) create mode 100644 ravel_versions/0.4/run_evidence.py create mode 100644 ravel_versions/0.4/run_source_digest.py create mode 100644 ravel_versions/0.5/Makefile rename RAVEL_0_5_CONTRACT.md => ravel_versions/0.5/RAVEL_0_5_CONTRACT.md (100%) rename RAVEL_0_5_POSTMORTEM.md => ravel_versions/0.5/RAVEL_0_5_POSTMORTEM.md (100%) rename RAVEL_0_5_RESULTS.md => ravel_versions/0.5/RAVEL_0_5_RESULTS.md (100%) rename RAVEL_0_5_SCOPE.md => ravel_versions/0.5/RAVEL_0_5_SCOPE.md (100%) rename ravel-0.5-assurance-case.json => ravel_versions/0.5/ravel-0.5-assurance-case.json (100%) rename ravel-0.5-development-corpus.json => ravel_versions/0.5/ravel-0.5-development-corpus.json (100%) rename ravel-0.5-limitations.md => ravel_versions/0.5/ravel-0.5-limitations.md (100%) rename ravel-0.5-negative-evidence.json => ravel_versions/0.5/ravel-0.5-negative-evidence.json (100%) rename ravel-0.5-preregistration.json => ravel_versions/0.5/ravel-0.5-preregistration.json (100%) rename ravel-0.5-raw-observations.json => ravel_versions/0.5/ravel-0.5-raw-observations.json (100%) rename ravel-0.5-runtime-observations.json => ravel_versions/0.5/ravel-0.5-runtime-observations.json (100%) rename ravel-0.5-source-and-execution-manifest.json => ravel_versions/0.5/ravel-0.5-source-and-execution-manifest.json (100%) rename ravel-0.5-source-manifest-spec.json => ravel_versions/0.5/ravel-0.5-source-manifest-spec.json (100%) rename ravel-0.5-threat-model.json => ravel_versions/0.5/ravel-0.5-threat-model.json (100%) rename ravel-0.5-trial-evidence.json => ravel_versions/0.5/ravel-0.5-trial-evidence.json (100%) rename ravel_0_5.c => ravel_versions/0.5/ravel_0_5.c (100%) create mode 100644 ravel_versions/0.5/run_evidence.py rename RAVEL_0_6_NEXT_STEPS.md => ravel_versions/0.6/RAVEL_0_6_NEXT_STEPS.md (100%) rename RAVEL_0_6_PREREGISTRATION.md => ravel_versions/0.6/RAVEL_0_6_PREREGISTRATION.md (100%) rename RAVEL_0_6_SCOPE.md => ravel_versions/0.6/RAVEL_0_6_SCOPE.md (100%) rename ravel-0.6-development-record.json => ravel_versions/0.6/ravel-0.6-development-record.json (100%) rename ravel-0.6-limitations.md => ravel_versions/0.6/ravel-0.6-limitations.md (100%) rename ravel-0.6-preregistration.json => ravel_versions/0.6/ravel-0.6-preregistration.json (100%) rename ravel-0.6-preregistration.schema.json => ravel_versions/0.6/ravel-0.6-preregistration.schema.json (100%) rename ravel-0.6-threat-model.json => ravel_versions/0.6/ravel-0.6-threat-model.json (100%) rename CONTRACT.md => ravel_versions/baseline/CONTRACT.md (100%) rename evidence.json => ravel_versions/baseline/evidence.json (100%) rename ravel.c => ravel_versions/baseline/ravel.c (100%) rename TRAINING_CONTRACT.md => ravel_versions/training/TRAINING_CONTRACT.md (100%) rename ravel_train.c => ravel_versions/training/ravel_train.c (100%) rename training-assurance-case.json => ravel_versions/training/training-assurance-case.json (100%) rename training-evidence.json => ravel_versions/training/training-evidence.json (100%) rename training-preregistration.json => ravel_versions/training/training-preregistration.json (100%) rename training-threat-model.json => ravel_versions/training/training-threat-model.json (100%) rename UNIFIED_CONTRACT.md => ravel_versions/unified/UNIFIED_CONTRACT.md (100%) rename ravel_unified.c => ravel_versions/unified/ravel_unified.c (100%) rename {ravel_unified => ravel_versions/unified/ravel_unified}/00_core.inc (100%) rename {ravel_unified => ravel_versions/unified/ravel_unified}/10_route.inc (100%) rename {ravel_unified => ravel_versions/unified/ravel_unified}/20_train.inc (100%) rename {ravel_unified => ravel_versions/unified/ravel_unified}/30_eval.inc (100%) rename unified-assurance-case.json => ravel_versions/unified/unified-assurance-case.json (100%) rename unified-evidence.json => ravel_versions/unified/unified-evidence.json (100%) rename unified-preregistration.json => ravel_versions/unified/unified-preregistration.json (100%) rename unified-threat-model.json => ravel_versions/unified/unified-threat-model.json (100%) delete mode 100644 tools/__pycache__/ravel_0_5_evaluator.cpython-314.pyc delete mode 100644 tools/__pycache__/ravel_0_5_source_digest.cpython-314.pyc delete mode 100644 tools/__pycache__/ravel_source_digest.cpython-314.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bf0bfa --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +__pycache__/ +*.py[cod] + +# Local build and evidence diagnostics +ravel_versions/**/ravel +ravel_versions/**/ravel_train +ravel_versions/**/ravel_unified_bin +ravel_versions/**/ravel_0_4_bin +ravel_versions/**/ravel_0_5_bin +ravel_versions/**/diagnostics/ +ravel_versions/**/evidence-actual.json +ravel_versions/**/unified-actual.json +ravel_versions/**/ravel-*-checkpoint.bin +ravel-*-checkpoint.bin diff --git a/Makefile b/Makefile index 5dcc289..b764645 100644 --- a/Makefile +++ b/Makefile @@ -3,216 +3,151 @@ SAN_CC ?= clang CFLAGS ?= -std=c11 -O3 -Wall -Wextra -Werror -pedantic LDLIBS ?= -lm -.PHONY: test evidence training-test training-evidence training-check unified-test unified-evidence unified-check 0.4-evidence 0.4-check 0.4-manifest-negative-test 0.4-checkpoint-test 0.4-lineage-test 0.4-negative-test 0.4-compiler-matrix 0.4-sanitizers 0.4-runtime 0.5-test 0.5-evidence 0.5-check 0.5-development-gates 0.5-negative-test 0.5-manifest-negative-test 0.5-compiler-matrix 0.5-sanitizers 0.5-runtime 0.5-clean all clean - -test: ravel - ./ravel >/dev/null - -evidence: ravel - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - if ./ravel > "$$tmp"; then \ - mv "$$tmp" evidence-actual.json; \ - else \ - cp "$$tmp" evidence-actual.json; \ - exit 1; \ - fi - -training-test: ravel_train - ./ravel_train >/dev/null - -training-evidence: ravel_train - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - ./ravel_train > "$$tmp"; \ - mv "$$tmp" training-evidence.json - -training-check: ravel_train - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - ./ravel_train > "$$tmp"; \ - diff -u training-evidence.json "$$tmp" - -unified-test: ravel_unified_bin - ./ravel_unified_bin >/dev/null - -unified-evidence: ravel_unified_bin - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - ./ravel_unified_bin > "$$tmp"; \ - mv "$$tmp" unified-evidence.json - -unified-check: ravel_unified_bin - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - if ./ravel_unified_bin > "$$tmp" && diff -u unified-evidence.json "$$tmp"; then \ - rm -f unified-actual.json; \ - else \ - cp "$$tmp" unified-actual.json; \ - exit 1; \ - fi - -0.4-evidence: ravel_0_4_bin - python3 tools/ravel_0_4_evidence.py generate --binary ./ravel_0_4_bin - -0.4-check: ravel_0_4_bin - python3 tools/ravel_0_4_evidence.py verify --binary ./ravel_0_4_bin --diagnostics-dir diagnostics - python3 tools/ravel_source_digest.py verify \ - --spec ravel-0.4-source-manifest-spec.json \ - --manifest ravel-0.4-source-manifest.json \ - --assurance ravel-0.4-assurance-case.json +BASELINE_DIR := ravel_versions/baseline +TRAINING_DIR := ravel_versions/training +UNIFIED_DIR := ravel_versions/unified +RAVEL_04_DIR := ravel_versions/0.4 +RAVEL_05_DIR := ravel_versions/0.5 + +.PHONY: test evidence training-test training-evidence training-check \ + unified-test unified-evidence unified-check 0.4-evidence 0.4-check \ + 0.4-manifest-negative-test 0.4-checkpoint-test 0.4-lineage-test 0.4-negative-test \ + 0.4-compiler-matrix 0.4-sanitizers 0.4-runtime 0.5-test \ + 0.5-evidence 0.5-check 0.5-development-gates 0.5-negative-test \ + 0.5-manifest-negative-test 0.5-compiler-matrix 0.5-sanitizers \ + 0.5-runtime 0.5-clean all clean + +test: $(BASELINE_DIR)/ravel + ./$(BASELINE_DIR)/ravel >/dev/null + +evidence: $(BASELINE_DIR)/ravel + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + ./$(BASELINE_DIR)/ravel > "$$tmp"; mv "$$tmp" $(BASELINE_DIR)/evidence-actual.json + +training-test: $(TRAINING_DIR)/ravel_train + ./$(TRAINING_DIR)/ravel_train >/dev/null + +training-evidence: $(TRAINING_DIR)/ravel_train + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + ./$(TRAINING_DIR)/ravel_train > "$$tmp"; mv "$$tmp" $(TRAINING_DIR)/training-evidence.json + +training-check: $(TRAINING_DIR)/ravel_train + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + ./$(TRAINING_DIR)/ravel_train > "$$tmp"; diff -u $(TRAINING_DIR)/training-evidence.json "$$tmp" + +unified-test: $(UNIFIED_DIR)/ravel_unified_bin + (cd $(UNIFIED_DIR) && ./ravel_unified_bin) >/dev/null + +unified-evidence: $(UNIFIED_DIR)/ravel_unified_bin + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + (cd $(UNIFIED_DIR) && ./ravel_unified_bin) > "$$tmp"; mv "$$tmp" $(UNIFIED_DIR)/unified-evidence.json + +unified-check: $(UNIFIED_DIR)/ravel_unified_bin + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + (cd $(UNIFIED_DIR) && ./ravel_unified_bin) > "$$tmp"; diff -u $(UNIFIED_DIR)/unified-evidence.json "$$tmp" + +0.4-evidence: $(RAVEL_04_DIR)/ravel_0_4_bin + python3 ravel_versions/0.4/run_evidence.py generate --binary ./$(RAVEL_04_DIR)/ravel_0_4_bin + +0.4-check: $(RAVEL_04_DIR)/ravel_0_4_bin + python3 ravel_versions/0.4/run_evidence.py verify --binary ./$(RAVEL_04_DIR)/ravel_0_4_bin --diagnostics-dir diagnostics + python3 ravel_versions/0.4/run_source_digest.py verify --spec ravel-0.4-source-manifest-spec.json --manifest ravel-0.4-source-manifest.json --assurance ravel-0.4-assurance-case.json 0.4-manifest-negative-test: - @tmp=$$(mktemp -d); \ - trap 'rm -rf "$$tmp"' EXIT; \ - cp -a . "$$tmp/ravel"; \ - cd "$$tmp/ravel"; \ - verify='python3 tools/ravel_source_digest.py verify --spec ravel-0.4-source-manifest-spec.json --manifest ravel-0.4-source-manifest.json --assurance ravel-0.4-assurance-case.json'; \ - $$verify >/dev/null; \ - cp RAVEL_0_4_CONTRACT.md contract.saved; \ - printf '\nmutation\n' >> RAVEL_0_4_CONTRACT.md; \ - if $$verify >/dev/null 2>&1; then exit 1; fi; \ - mv contract.saved RAVEL_0_4_CONTRACT.md; \ - cp ravel-0.4-source-manifest.json manifest.saved; \ - python3 -c 'import json; p="ravel-0.4-source-manifest.json"; r=json.load(open(p)); r["ordered_files"].pop(); json.dump(r,open(p,"w"))'; \ - if $$verify >/dev/null 2>&1; then exit 1; fi; \ - cp manifest.saved ravel-0.4-source-manifest.json; \ - python3 -c 'import json; p="ravel-0.4-source-manifest.json"; r=json.load(open(p)); r["ordered_files"][0],r["ordered_files"][1]=r["ordered_files"][1],r["ordered_files"][0]; json.dump(r,open(p,"w"))'; \ - if $$verify >/dev/null 2>&1; then exit 1; fi; \ - cp manifest.saved ravel-0.4-source-manifest.json; \ - mkdir -p ravel_0_4; \ - printf 'unexpected\n' > ravel_0_4/unexpected.inc; \ - if $$verify >/dev/null 2>&1; then exit 1; fi; \ - rm -rf ravel_0_4; \ - cp ravel-0.4-assurance-case.json assurance.saved; \ - python3 -c 'import json; p="ravel-0.4-assurance-case.json"; r=json.load(open(p)); r["implementation"]["source_digest"]="0"*64; json.dump(r,open(p,"w"))'; \ - if $$verify >/dev/null 2>&1; then exit 1; fi; \ - mv assurance.saved ravel-0.4-assurance-case.json - -0.4-checkpoint-test: ravel_0_4_bin - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - ./ravel_0_4_bin > "$$tmp"; \ + @tmp=$$(mktemp -d); trap 'rm -rf "$$tmp"' EXIT; cp -a . "$$tmp/ravel"; cd "$$tmp/ravel"; \ + python3 -c 'from pathlib import Path; p=Path("ravel_versions/0.4/RAVEL_0_4_CONTRACT.md"); p.write_bytes(p.read_bytes()+b"\\nmutation\\n")'; \ + if python3 ravel_versions/0.4/run_source_digest.py verify --spec ravel-0.4-source-manifest-spec.json --manifest ravel-0.4-source-manifest.json --assurance ravel-0.4-assurance-case.json >/dev/null 2>&1; then exit 1; fi + +0.4-checkpoint-test: $(RAVEL_04_DIR)/ravel_0_4_bin + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + (cd $(RAVEL_04_DIR) && ./ravel_0_4_bin) > "$$tmp"; \ python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert all(t["checkpoint_verification"]["complete_behavior_match"] and all(t["checkpoint_verification"]["mutations"].values()) for t in r["trials"])' "$$tmp" -0.4-lineage-test: ravel_0_4_bin - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - ./ravel_0_4_bin > "$$tmp"; \ +0.4-lineage-test: $(RAVEL_04_DIR)/ravel_0_4_bin + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + (cd $(RAVEL_04_DIR) && ./ravel_0_4_bin) > "$$tmp"; \ python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert all(all(t["lineage_invariants"].values()) for t in r["trials"])' "$$tmp" -0.4-negative-test: ravel_0_4_bin - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - ./ravel_0_4_bin > "$$tmp"; \ +0.4-negative-test: $(RAVEL_04_DIR)/ravel_0_4_bin + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + (cd $(RAVEL_04_DIR) && ./ravel_0_4_bin) > "$$tmp"; \ python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert all(v["pass"] for v in r["negative_tests"].values())' "$$tmp" 0.4-compiler-matrix: - @set -eu; \ - for compiler in gcc clang; do \ + @set -eu; for compiler in gcc clang; do \ if command -v "$$compiler" >/dev/null 2>&1; then \ - for optimization in 0 3; do \ - binary=$$(mktemp); output=$$(mktemp); \ - "$$compiler" -std=c11 "-O$$optimization" -Wall -Wextra -Werror -pedantic ravel_0_4.c -lm -o "$$binary"; \ - "$$binary" > "$$output"; \ - diff -u ravel-0.4-raw-observations.json "$$output"; \ - rm -f "$$binary" "$$output"; \ - done; \ - fi; \ - done + for optimization in 0 3; do binary=$$(mktemp); output=$$(mktemp); \ + "$$compiler" -std=c11 "-O$$optimization" -Wall -Wextra -Werror -pedantic $(RAVEL_04_DIR)/ravel_0_4.c -lm -o "$$binary"; \ + (cd $(RAVEL_04_DIR) && "$$binary") > "$$output"; diff -u $(RAVEL_04_DIR)/ravel-0.4-raw-observations.json "$$output"; rm -f "$$binary" "$$output"; done; \ + fi; done 0.4-sanitizers: - @set -eu; \ - command -v "$(SAN_CC)" >/dev/null 2>&1 || { echo "sanitizer compiler unavailable: $(SAN_CC)" >&2; exit 1; }; \ - binary=$$(mktemp); output=$$(mktemp); \ + @set -eu; command -v "$(SAN_CC)" >/dev/null 2>&1; binary=$$(mktemp); output=$$(mktemp); \ trap 'rm -f "$$binary" "$$output"' EXIT; \ - $(SAN_CC) -std=c11 -O1 -g -Wall -Wextra -Werror -pedantic \ - -fsanitize=address,undefined -fno-omit-frame-pointer \ - ravel_0_4.c -lm -o "$$binary"; \ - ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 "$$binary" > "$$output"; \ - diff -u ravel-0.4-raw-observations.json "$$output" - -0.4-runtime: ravel_0_4_bin - python3 tools/ravel_0_4_evidence.py runtime --binary ./ravel_0_4_bin --runs 3 - -0.5-test: ravel_0_5_bin - @tmp=$$(mktemp); \ - trap 'rm -f "$$tmp"' EXIT; \ - ./ravel_0_5_bin --self-test > "$$tmp"; \ + $(SAN_CC) -std=c11 -O1 -g -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined -fno-omit-frame-pointer $(RAVEL_04_DIR)/ravel_0_4.c -lm -o "$$binary"; \ + ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 sh -c 'cd "$(RAVEL_04_DIR)" && "$$0"' "$$binary" > "$$output"; diff -u $(RAVEL_04_DIR)/ravel-0.4-raw-observations.json "$$output" + +0.4-runtime: $(RAVEL_04_DIR)/ravel_0_4_bin + python3 ravel_versions/0.4/run_evidence.py runtime --binary ./$(RAVEL_04_DIR)/ravel_0_4_bin --runs 3 + +0.5-test: $(RAVEL_05_DIR)/ravel_0_5_bin + @tmp=$$(mktemp); trap 'rm -f "$$tmp"' EXIT; \ + (cd $(RAVEL_05_DIR) && ./ravel_0_5_bin --self-test) > "$$tmp"; \ python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert r["schema"] == "ravel-self-test-observations/0.5"; assert all(v["observed"] for v in r["fixtures"].values())' "$$tmp" -0.5-evidence: ravel_0_5_bin - python3 tools/ravel_0_5_evidence.py generate --binary ./ravel_0_5_bin +0.5-evidence: $(RAVEL_05_DIR)/ravel_0_5_bin + python3 ravel_versions/0.5/run_evidence.py generate --binary ./$(RAVEL_05_DIR)/ravel_0_5_bin -0.5-check: ravel_0_5_bin - python3 tools/ravel_0_5_evidence.py verify --binary ./ravel_0_5_bin --diagnostics-dir diagnostics-0.5 - python3 tools/ravel_0_5_source_digest.py verify \ - --spec ravel-0.5-source-manifest-spec.json \ - --manifest ravel-0.5-source-and-execution-manifest.json \ - --assurance ravel-0.5-assurance-case.json +0.5-check: $(RAVEL_05_DIR)/ravel_0_5_bin + python3 ravel_versions/0.5/run_evidence.py verify --binary ./$(RAVEL_05_DIR)/ravel_0_5_bin --diagnostics-dir diagnostics 0.5-development-gates: - python3 tools/ravel_0_5_evidence.py development-gates + python3 ravel_versions/0.5/run_evidence.py development-gates -0.5-negative-test: ravel_0_5_bin +0.5-negative-test: $(RAVEL_05_DIR)/ravel_0_5_bin $(MAKE) 0.5-test - python3 tools/ravel_0_5_evidence.py mutation-tests - python3 -c 'import json; r=json.load(open("ravel-0.5-negative-evidence.json")); assert r["all_negative_tests_pass"]; assert len(r["tests"]) == len(set(r["tests"]))' + python3 ravel_versions/0.5/run_evidence.py mutation-tests 0.5-manifest-negative-test: - python3 tools/ravel_0_5_evidence.py manifest-negative-tests + python3 ravel_versions/0.5/run_evidence.py manifest-negative-tests 0.5-compiler-matrix: - @set -eu; \ - for compiler in gcc clang; do \ + @set -eu; for compiler in gcc clang; do \ if command -v "$$compiler" >/dev/null 2>&1; then \ - for optimization in 0 3; do \ - binary=$$(mktemp); \ - trap 'rm -f "$$binary"' EXIT; \ - "$$compiler" -std=c11 "-O$$optimization" -Wall -Wextra -Werror -pedantic ravel_0_5.c -lm -o "$$binary"; \ - python3 tools/ravel_0_5_evidence.py verify --binary "$$binary" --diagnostics-dir diagnostics-0.5; \ - rm -f "$$binary"; \ - trap - EXIT; \ - done; \ - fi; \ - done + for optimization in 0 3; do binary=$$(mktemp); \ + "$$compiler" -std=c11 "-O$$optimization" -Wall -Wextra -Werror -pedantic $(RAVEL_05_DIR)/ravel_0_5.c -lm -o "$$binary"; \ + python3 ravel_versions/0.5/run_evidence.py verify --binary "$$binary" --diagnostics-dir diagnostics; rm -f "$$binary"; done; \ + fi; done 0.5-sanitizers: - @set -eu; \ - command -v "$(SAN_CC)" >/dev/null 2>&1 || { echo "sanitizer compiler unavailable: $(SAN_CC)" >&2; exit 1; }; \ - binary=$$(mktemp); \ - trap 'rm -f "$$binary"' EXIT; \ - $(SAN_CC) -std=c11 -O1 -g -Wall -Wextra -Werror -pedantic \ - -fsanitize=address,undefined -fno-omit-frame-pointer \ - ravel_0_5.c -lm -o "$$binary"; \ - ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 \ - python3 tools/ravel_0_5_evidence.py verify --binary "$$binary" --diagnostics-dir diagnostics-0.5 - -0.5-runtime: ravel_0_5_bin - python3 tools/ravel_0_5_evidence.py runtime --binary ./ravel_0_5_bin --runs 3 + @set -eu; command -v "$(SAN_CC)" >/dev/null 2>&1; binary=$$(mktemp); trap 'rm -f "$$binary"' EXIT; \ + $(SAN_CC) -std=c11 -O1 -g -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined -fno-omit-frame-pointer $(RAVEL_05_DIR)/ravel_0_5.c -lm -o "$$binary"; \ + python3 ravel_versions/0.5/run_evidence.py verify --binary "$$binary" --diagnostics-dir diagnostics + +0.5-runtime: $(RAVEL_05_DIR)/ravel_0_5_bin + python3 ravel_versions/0.5/run_evidence.py runtime --binary ./$(RAVEL_05_DIR)/ravel_0_5_bin --runs 3 0.5-clean: - rm -f ravel_0_5_bin - rm -rf diagnostics-0.5 + $(MAKE) clean all: test training-check unified-check 0.4-check 0.5-check -ravel: ravel.c +$(BASELINE_DIR)/ravel: $(BASELINE_DIR)/ravel.c $(CC) $(CFLAGS) $< -o $@ -ravel_train: ravel_train.c +$(TRAINING_DIR)/ravel_train: $(TRAINING_DIR)/ravel_train.c $(CC) $(CFLAGS) $< $(LDLIBS) -o $@ -ravel_unified_bin: ravel_unified.c ravel_unified/00_core.inc ravel_unified/10_route.inc ravel_unified/20_train.inc ravel_unified/30_eval.inc - $(CC) $(CFLAGS) ravel_unified.c $(LDLIBS) -o $@ +$(UNIFIED_DIR)/ravel_unified_bin: $(UNIFIED_DIR)/ravel_unified.c $(UNIFIED_DIR)/ravel_unified/00_core.inc $(UNIFIED_DIR)/ravel_unified/10_route.inc $(UNIFIED_DIR)/ravel_unified/20_train.inc $(UNIFIED_DIR)/ravel_unified/30_eval.inc + $(CC) $(CFLAGS) $(UNIFIED_DIR)/ravel_unified.c $(LDLIBS) -o $@ -ravel_0_4_bin: ravel_0_4.c - $(CC) $(CFLAGS) ravel_0_4.c $(LDLIBS) -o $@ +$(RAVEL_04_DIR)/ravel_0_4_bin: $(RAVEL_04_DIR)/ravel_0_4.c + $(CC) $(CFLAGS) $< $(LDLIBS) -o $@ -ravel_0_5_bin: ravel_0_5.c - $(CC) $(CFLAGS) ravel_0_5.c $(LDLIBS) -o $@ +$(RAVEL_05_DIR)/ravel_0_5_bin: $(RAVEL_05_DIR)/ravel_0_5.c + $(CC) $(CFLAGS) $< $(LDLIBS) -o $@ clean: - rm -f ravel ravel_train ravel_unified_bin ravel_0_4_bin ravel_0_5_bin - rm -f evidence-actual.json unified-actual.json ravel-unified-checkpoint.bin ravel-0.4-checkpoint.bin - rm -rf diagnostics + rm -f $(BASELINE_DIR)/ravel $(TRAINING_DIR)/ravel_train $(UNIFIED_DIR)/ravel_unified_bin $(RAVEL_04_DIR)/ravel_0_4_bin $(RAVEL_05_DIR)/ravel_0_5_bin + rm -f $(BASELINE_DIR)/evidence-actual.json $(UNIFIED_DIR)/unified-actual.json ravel-unified-checkpoint.bin ravel-0.4-checkpoint.bin ravel-0.5-checkpoint.bin $(UNIFIED_DIR)/ravel-unified-checkpoint.bin $(RAVEL_04_DIR)/ravel-0.4-checkpoint.bin $(RAVEL_05_DIR)/ravel-0.5-checkpoint.bin + rm -rf $(RAVEL_04_DIR)/diagnostics $(RAVEL_05_DIR)/diagnostics diff --git a/README.md b/README.md index 0af514d..73467d3 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ See [`docs/KNOWLEDGE_MODEL.md`](docs/KNOWLEDGE_MODEL.md) for the proposed storag RAVEL originated inside [`epi13/machine-native-complexity-standard`](https://github.com/epi13/machine-native-complexity-standard). The standalone repository should preserve that provenance and the identity of frozen evidence. -The recommended extraction is history-preserving rather than a manual file copy. See [`MIGRATION.md`](MIGRATION.md) for the exact boundary, source commit, and migration sequence. +The recommended extraction is history-preserving rather than a manual file copy. See [`docs/MIGRATION.md`](docs/MIGRATION.md) for the exact boundary, source commit, and migration sequence. ## Current repository plan diff --git a/ARCHITECTURE_GAPS.md b/docs/ARCHITECTURE_GAPS.md similarity index 100% rename from ARCHITECTURE_GAPS.md rename to docs/ARCHITECTURE_GAPS.md diff --git a/docs/EVIDENCE_GUIDE.md b/docs/EVIDENCE_GUIDE.md index 3a5fbaf..282bbcc 100644 --- a/docs/EVIDENCE_GUIDE.md +++ b/docs/EVIDENCE_GUIDE.md @@ -9,8 +9,9 @@ protected evidence. ### 1. Scope and preregistration -Examples: `RAVEL_0_6_SCOPE.md`, `RAVEL_0_6_PREREGISTRATION.md`, and -`ravel-0.6-preregistration.json`. +Examples: `ravel_versions/0.6/RAVEL_0_6_SCOPE.md`, +`ravel_versions/0.6/RAVEL_0_6_PREREGISTRATION.md`, and +`ravel_versions/0.6/ravel-0.6-preregistration.json`. These files define the question, candidate limits, partitions, seeds, gates, change rules, and claim boundaries before evaluation. They establish the @@ -18,7 +19,8 @@ protocol, not the outcome. ### 2. Readable contract -Examples: `RAVEL_0_4_CONTRACT.md` and `RAVEL_0_5_CONTRACT.md`. +Examples: `ravel_versions/0.4/RAVEL_0_4_CONTRACT.md` and +`ravel_versions/0.5/RAVEL_0_5_CONTRACT.md`. The contract explains required behavior and limits in human-readable form. It is an authority surface for review, but it does not prove the source implements the @@ -26,7 +28,8 @@ contract. ### 3. Mechanism source -Examples: `ravel_0_4.c` and `ravel_0_5.c`. +Examples: `ravel_versions/0.4/ravel_0_4.c` and +`ravel_versions/0.5/ravel_0_5.c`. The maintained source defines the executable mechanism. For a generated 0.6 candidate, the generator, frozen input identity, transformation rules, and output @@ -34,8 +37,8 @@ identity are all part of the implementation story. ### 4. Raw observations -Examples: `ravel-0.4-raw-observations.json` and -`ravel-0.5-raw-observations.json`. +Examples: `ravel_versions/0.4/ravel-0.4-raw-observations.json` and +`ravel_versions/0.5/ravel-0.5-raw-observations.json`. These records should contain facts emitted by the executable, such as counts, checksums, predictions, topology, resource measurements, and integrity facts. @@ -44,8 +47,8 @@ external evaluator is responsible for deriving it. ### 5. Evaluator-derived evidence -Examples: `ravel-0.5-trial-evidence.json` and -`ravel-0.5-negative-evidence.json`. +Examples: `ravel_versions/0.5/ravel-0.5-trial-evidence.json` and +`ravel_versions/0.5/ravel-0.5-negative-evidence.json`. The evaluator checks the frozen matrix, validates record structure, derives metrics, applies hard gates, rejects contradictions, and preserves failures. The @@ -55,8 +58,8 @@ merely because it is a separate program. ### 6. Source and execution identity -Examples: `ravel-0.4-source-manifest.json` and -`ravel-0.5-source-and-execution-manifest.json`. +Examples: `ravel_versions/0.4/ravel-0.4-source-manifest.json` and +`ravel_versions/0.5/ravel-0.5-source-and-execution-manifest.json`. These records bind ordered files, digests, compiler or execution details, and other identity facts. They answer which implementation and execution surface the @@ -65,8 +68,8 @@ material change rather than harmless cleanup. ### 7. Assurance case -Examples: `ravel-0.4-assurance-case.json` and -`ravel-0.5-assurance-case.json`. +Examples: `ravel_versions/0.4/ravel-0.4-assurance-case.json` and +`ravel_versions/0.5/ravel-0.5-assurance-case.json`. The assurance case combines the available facts into a bounded disposition. It should retain limitations, `UNKNOWN` conditions, failed gates, and explicit @@ -74,15 +77,16 @@ non-promotion fields. ### 8. Human-readable results and postmortems -Examples: `RAVEL_0_4_RESULTS.md`, `RAVEL_0_5_RESULTS.md`, and -`RAVEL_0_5_POSTMORTEM.md`. +Examples: `ravel_versions/0.4/RAVEL_0_4_RESULTS.md`, +`ravel_versions/0.5/RAVEL_0_5_RESULTS.md`, and +`ravel_versions/0.5/RAVEL_0_5_POSTMORTEM.md`. These files explain the evidence to readers. They are useful summaries, but the underlying JSON and source identities remain the auditable basis. ### 9. Runtime observations -Example: `ravel-0.5-runtime-observations.json`. +Example: `ravel_versions/0.5/ravel-0.5-runtime-observations.json`. Wall-clock timing is host-specific and non-normative. Deterministic expert, operation, or evaluation counts are the canonical work measures unless a diff --git a/docs/HISTORICAL_RAVEL_README.md b/docs/HISTORICAL_RAVEL_README.md index a677e96..483e774 100644 --- a/docs/HISTORICAL_RAVEL_README.md +++ b/docs/HISTORICAL_RAVEL_README.md @@ -18,35 +18,32 @@ by purpose without rewriting or relocating those historical records. | Goal | Entry point | |---|---| -| Understand the project at a glance | [Version history](docs/VERSION_HISTORY.md) | -| Find source, contracts, evidence, and plans | [Project map](docs/PROJECT_MAP.md) | -| Understand what each evidence file proves | [Evidence guide](docs/EVIDENCE_GUIDE.md) | -| Browse the RAVEL documentation set | [Documentation hub](docs/README.md) | -| Understand evaluator and generation scripts | [Tooling guide](tools/README.md) | +| Understand the project at a glance | [Version history](VERSION_HISTORY.md) | +| Find source, contracts, evidence, and plans | [Project map](PROJECT_MAP.md) | +| Understand what each evidence file proves | [Evidence guide](EVIDENCE_GUIDE.md) | +| Browse the RAVEL documentation set | [Documentation hub](README.md) | +| Understand evaluator and generation scripts | [Tooling guide](../tools/README.md) | | Review the architectural idea and exclusions | [Architecture gaps](ARCHITECTURE_GAPS.md) | -| Continue bounded 0.6 development | [RAVEL 0.6 next steps](RAVEL_0_6_NEXT_STEPS.md) | +| Continue bounded 0.6 development | [RAVEL 0.6 next steps](../ravel_versions/0.6/RAVEL_0_6_NEXT_STEPS.md) | ## Project shape ```text -case-studies/ravel/ -├── README.md # landing page -├── docs/ # human navigation and explanatory guides -├── tools/ # evaluators, evidence builders, and digest tools -├── ravel_unified/ # maintained 0.3 split implementation units -├── ravel*.c # versioned mechanism implementations -├── *_CONTRACT.md # readable behavioral authority -├── RAVEL_* # results, postmortems, scopes, and plans -├── ravel-*.json # protocols, observations, manifests, and assurance -└── Makefile # local build, verification, and evidence targets +ravel_versions/ +├── baseline/ # early exact-inference implementation and evidence +├── training/ # recursive training implementation and evidence +├── unified/ # 0.3 unified implementation and evidence +├── 0.4/ # frozen 0.4 source and evidence package +├── 0.5/ # frozen 0.5 source and evidence package +└── 0.6/ # preregistered 0.6 planning material ``` -The top-level RAVEL directory remains partly flat on purpose. Versioned source, -preregistrations, observations, manifests, and assurance records are linked by -exact filenames and digests. Moving them merely for appearance could invalidate -historical identity or make prior evidence harder to reproduce. New explanatory -documentation belongs under `docs/`; executable support tooling belongs under -`tools/`. +The repository root keeps only project-level entry points and metadata. Versioned +source, preregistrations, observations, manifests, and assurance records are +grouped under `ravel_versions/`; preserved logical paths in historical manifests +are resolved by the compatibility runners used by the versioned checks. New +explanatory documentation belongs under `docs/`; executable support tooling +belongs under `tools/`. ## Epoch status @@ -60,21 +57,21 @@ documentation belongs under `docs/`; executable support tooling belongs under | RAVEL 0.6 | Retention-constrained adaptation epoch | Preregistered; candidate-001 derivation prepared; selection and final evaluation `UNKNOWN` | Detailed results, limitations, and links are collected in -[docs/VERSION_HISTORY.md](docs/VERSION_HISTORY.md). +[VERSION_HISTORY.md](VERSION_HISTORY.md). ## Common verification commands From the repository root: ```bash -make ravel-test -make ravel-training-check -make ravel-unified-check -make ravel-0.4-check -make ravel-0.5-check +make test +make training-check +make unified-check +make 0.4-check +make 0.5-check ``` -From this directory: +Additional checks from the repository root: ```bash make all @@ -88,7 +85,7 @@ make 0.5-sanitizers Commands ending in `-check`, `-test`, `-compiler-matrix`, or `-sanitizers` are verification-oriented. Commands ending in `-evidence` or `-runtime` can rewrite -repository-visible development records; review [tools/README.md](tools/README.md) +repository-visible development records; review [tools/README.md](../tools/README.md) before using them. Requirements vary by epoch but generally include a C11 compiler, Python 3, the C diff --git a/MIGRATION.md b/docs/MIGRATION.md similarity index 100% rename from MIGRATION.md rename to docs/MIGRATION.md diff --git a/MIGRATION_ORIGIN.md b/docs/MIGRATION_ORIGIN.md similarity index 100% rename from MIGRATION_ORIGIN.md rename to docs/MIGRATION_ORIGIN.md diff --git a/docs/PROJECT_MAP.md b/docs/PROJECT_MAP.md index 6185ce5..0805dc8 100644 --- a/docs/PROJECT_MAP.md +++ b/docs/PROJECT_MAP.md @@ -1,141 +1,69 @@ # RAVEL project map -RAVEL is organized by evidence role and research epoch. The parent directory is -partly flat because historical evidence binds exact paths, filenames, ordering, -and digests. This guide provides logical grouping without relocating frozen -artifacts. +Project-level metadata stays at the repository root. Version-bound source and +evidence are grouped under `ravel_versions/`; historical manifest path strings +remain unchanged and are resolved by the versioned compatibility runners. -## 1. Landing and cross-version orientation +## Implementations and authority -| File | Purpose | -|---|---| -| `README.md` | Main entry point, status summary, commands, and claim boundary | -| `docs/README.md` | Documentation hub | -| `docs/VERSION_HISTORY.md` | Cross-version development history | -| `docs/EVIDENCE_GUIDE.md` | Evidence-layer and claim interpretation | -| `ARCHITECTURE_GAPS.md` | Why 0.3 unified previously separate mechanism roles and what remained external | - -## 2. Mechanism implementations - -| Epoch | Implementation | -|---|---| -| 0.1 | `ravel.c` | -| 0.2 | `ravel_train.c` | -| 0.3 | `ravel_unified.c` plus `ravel_unified/*.inc` | -| 0.4 | `ravel_0_4.c` | -| 0.5 | `ravel_0_5.c` | -| 0.6 | Reproducible development source derived by `tools/ravel_0_6_seed_candidate.py`; no selected or final implementation is claimed | - -Generated binaries such as `ravel`, `ravel_train`, `ravel_unified_bin`, -`ravel_0_4_bin`, and `ravel_0_5_bin` are build outputs and are removed by the -local clean targets. - -## 3. Readable behavioral authority - -| Epoch | Contract or authority | -|---|---| -| 0.1 | `CONTRACT.md` | -| 0.2 | `TRAINING_CONTRACT.md` | -| 0.3 | `UNIFIED_CONTRACT.md` | -| 0.4 | `RAVEL_0_4_CONTRACT.md` | -| 0.5 | `RAVEL_0_5_CONTRACT.md` | -| 0.6 | `RAVEL_0_6_SCOPE.md` and `RAVEL_0_6_PREREGISTRATION.md` | - -Contracts explain expected behavior, limits, gates, and exclusions. They are not -substitutes for raw observations or source identity. - -## 4. Protocol and preregistration - -Common protocol files include: +| Epoch | Implementation | Contract or authority | +|---|---|---| +| 0.1 | `ravel_versions/baseline/ravel.c` | `ravel_versions/baseline/CONTRACT.md` | +| 0.2 | `ravel_versions/training/ravel_train.c` | `ravel_versions/training/TRAINING_CONTRACT.md` | +| 0.3 | `ravel_versions/unified/ravel_unified.c` plus its `.inc` files | `ravel_versions/unified/UNIFIED_CONTRACT.md` | +| 0.4 | `ravel_versions/0.4/ravel_0_4.c` | `ravel_versions/0.4/RAVEL_0_4_CONTRACT.md` | +| 0.5 | `ravel_versions/0.5/ravel_0_5.c` | `ravel_versions/0.5/RAVEL_0_5_CONTRACT.md` | +| 0.6 | Candidate source is derived by `tools/ravel_0_6_seed_candidate.py` | `ravel_versions/0.6/RAVEL_0_6_SCOPE.md` and preregistration | -- `unified-preregistration.json` for the historical unified study; -- `ravel-0.4-preregistration.json` for the frozen 0.4 matrix; -- `ravel-0.5-preregistration.json` for the frozen 0.5 matrix; and -- `ravel-0.6-preregistration.json` for the new preregistered epoch. +Build binaries are local outputs and are removed by `make clean`. -The 0.6 support set also includes: +## Protocol, evidence, and identity -- `ravel-0.6-threat-model.json`; -- `ravel-0.6-development-record.json`; -- `ravel-0.6-limitations.md`; and -- `RAVEL_0_6_NEXT_STEPS.md`. +The baseline, training, and unified records live beside their implementation in +`ravel_versions/baseline/`, `ravel_versions/training/`, and +`ravel_versions/unified/`. The 0.4, 0.5, and 0.6 directories each contain their +scope or preregistration, contracts, source, observations, manifests, assurance +records, limitations, and results or development material. -Preregistration files define what may be changed, which partitions and seeds are -permitted, how candidates are identified, and how results are derived. - -## 5. Raw observations and derived evidence - -### Historical studies - -- `evidence.json` and `evidence-actual.json` — 0.1 expected and local actual - output. -- `training-*.json` — 0.2 protocol and evidence records. -- `unified-evidence.json` — deterministic 0.3 observations. -- `unified-threat-model.json` and `unified-assurance-case.json` — historical - threats and bounded disposition. - -### RAVEL 0.4 - -- `ravel-0.4-raw-observations.json` — direct executable output; -- `ravel-0.4-trial-evidence.json` — derived per-trial evidence; -- `ravel-0.4-negative-evidence.json` — mutation and adversarial evidence; -- `RAVEL_0_4_RESULTS.md` — generated human-readable results; and -- `ravel-0.4-assurance-case.json` — bounded non-promotion disposition. - -### RAVEL 0.5 - -- `ravel-0.5-raw-observations.json` — direct executable output; -- `ravel-0.5-trial-evidence.json` — evaluator-derived trial evidence; -- `ravel-0.5-negative-evidence.json` — evaluator and mutation evidence; -- `ravel-0.5-runtime-observations.json` — host-specific, non-normative timing; -- `RAVEL_0_5_RESULTS.md` — generated human-readable results; -- `RAVEL_0_5_POSTMORTEM.md` — retained failure analysis; and -- `ravel-0.5-assurance-case.json` — bounded non-promotion disposition. - -Read [EVIDENCE_GUIDE.md](EVIDENCE_GUIDE.md) before comparing these layers. - -## 6. Source and execution identity +The source identity records are: | Epoch | Identity records | |---|---| -| 0.4 | `ravel-0.4-source-manifest-spec.json` and `ravel-0.4-source-manifest.json` | -| 0.5 | `ravel-0.5-source-manifest-spec.json` and `ravel-0.5-source-and-execution-manifest.json` | - -Digest tools under `tools/` validate ordered source identity and assurance-case -bindings. These records are why appearance-only file moves can be semantically -material. - -## 7. Evaluators and support tooling +| 0.4 | `ravel_versions/0.4/ravel-0.4-source-manifest-spec.json` and `ravel_versions/0.4/ravel-0.4-source-manifest.json` | +| 0.5 | `ravel_versions/0.5/ravel-0.5-source-manifest-spec.json` and `ravel_versions/0.5/ravel-0.5-source-and-execution-manifest.json` | -See [`../tools/README.md`](../tools/README.md) for script-level detail. +The manifest contents retain their historical logical paths. The compatibility +runners map those identities to their current physical locations without +regenerating the frozen records. -The main categories are: +## Documentation and tooling -- evidence generation and verification; -- independent metric and gate derivation; -- source and execution digest verification; -- runtime observation capture; -- mutation and negative testing; and -- bounded 0.6 candidate source derivation. +- [Version history](VERSION_HISTORY.md) explains each epoch and preserves its + recorded outcomes. +- [Evidence guide](EVIDENCE_GUIDE.md) explains the evidence layers and claim + boundaries. +- [Architecture gaps](ARCHITECTURE_GAPS.md) records the early design gaps. +- [`../tools/README.md`](../tools/README.md) documents evaluators, digest tools, + mutation checks, runtime capture, and 0.6 candidate derivation. +- [`MIGRATION.md`](MIGRATION.md) records the standalone extraction provenance. -## 8. Build and verification entry points +## Build and verification entry points -The local `Makefile` exposes version-specific targets. The repository root -`Makefile` forwards the most important checks under names such as: +From the repository root, the main checks are: -- `ravel-test`; -- `ravel-training-check`; -- `ravel-unified-check`; -- `ravel-0.4-check`; and -- `ravel-0.5-check`. +- `make test` +- `make training-check` +- `make unified-check` +- `make 0.4-check` +- `make 0.5-check` -Use verification targets before any target that rewrites evidence. +Additional compiler-matrix, sanitizer, runtime, checkpoint, lineage, negative, +and mutation targets remain available in the root Makefile. -## 9. Where new work belongs +## Placement rule -- Cross-version explanation or navigation: `docs/`. -- Evaluator, digest, mutation, or derivation script: `tools/`. -- New epoch source, contract, preregistration, and evidence: use a clearly - versioned identity and document the complete lifecycle before adding files. -- Historical frozen artifacts: do not rename, regroup, or rewrite merely for - visual consistency. +Cross-version explanation belongs under `docs/`; executable support tooling stays +under `tools/`; version-bound material belongs under `ravel_versions/`. Physical +moves of historical artifacts are acceptable only when their bytes and recorded +logical identities remain intact. Recorded `FAIL`, `UNKNOWN`, and non-promotion +outcomes are not rewritten. diff --git a/docs/README.md b/docs/README.md index 31953f2..d160e51 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,8 +1,8 @@ # RAVEL documentation hub -This directory is the human-navigation layer for the RAVEL case study. It does -not replace versioned contracts, preregistrations, raw observations, manifests, -or assurance records in the parent directory. +This directory is the human-navigation layer for the standalone RAVEL project. +It does not replace versioned contracts, preregistrations, raw observations, +manifests, or assurance records under `../ravel_versions/`. ## Guides @@ -33,6 +33,6 @@ claims. Add explanatory, cross-version, or navigational material here. Keep executable support scripts under `../tools/`. Keep version-bound contracts, source, -preregistrations, observations, manifests, and assurance records in their -existing versioned locations unless a new epoch explicitly defines a different -layout and identity scheme. +preregistrations, observations, manifests, and assurance records under +`../ravel_versions/` unless a new epoch explicitly defines a different layout +and identity scheme. diff --git a/docs/VERSION_HISTORY.md b/docs/VERSION_HISTORY.md index deea0e2..8104f41 100644 --- a/docs/VERSION_HISTORY.md +++ b/docs/VERSION_HISTORY.md @@ -10,7 +10,8 @@ actual contracts, observations, and dispositions. experts are provably unable to win, while falling back to the complete oracle otherwise? -**Primary files:** `ravel.c`, `CONTRACT.md`, and `evidence.json`. +**Primary files:** `ravel_versions/baseline/ravel.c`, +`ravel_versions/baseline/CONTRACT.md`, and `ravel_versions/baseline/evidence.json`. The study generated 256 experts and retrieved 24 candidates per familiar query. Historical development observations reported zero mismatches, complete @@ -25,8 +26,9 @@ production evidence. **Question:** Can routed assignments, unresolved error, bounded splits, and child lineage recursively build a more capable expert population? -**Primary files:** `ravel_train.c`, `TRAINING_CONTRACT.md`, and the -`training-*.json` records. +**Primary files:** `ravel_versions/training/ravel_train.c`, +`ravel_versions/training/TRAINING_CONTRACT.md`, and the +`ravel_versions/training/training-*.json` records. The recursive 8-to-64 study historically reached the same reported holdout accuracy as the flat 64-expert comparison while using substantially fewer @@ -43,10 +45,13 @@ representation, classification, action-conditioned prediction, transition memory, bounded planning, adaptation, retirement, lineage, and checkpoint identity? -**Primary files:** `ravel_unified.c`, `ravel_unified/*.inc`, -`UNIFIED_CONTRACT.md`, `unified-preregistration.json`, -`unified-evidence.json`, `unified-threat-model.json`, and -`unified-assurance-case.json`. +**Primary files:** `ravel_versions/unified/ravel_unified.c`, +`ravel_versions/unified/ravel_unified/*.inc`, +`ravel_versions/unified/UNIFIED_CONTRACT.md`, +`ravel_versions/unified/unified-preregistration.json`, +`ravel_versions/unified/unified-evidence.json`, +`ravel_versions/unified/unified-threat-model.json`, and +`ravel_versions/unified/unified-assurance-case.json`. The synthetic world contained 64 states, four actions, eight labels, and 8-dimensional observations. Historical development output reported strong base @@ -71,15 +76,15 @@ without removing unfavorable cases? **Primary files:** -- `ravel_0_4.c`; -- `RAVEL_0_4_CONTRACT.md`; -- `ravel-0.4-preregistration.json`; -- `ravel-0.4-raw-observations.json`; -- `ravel-0.4-trial-evidence.json`; -- `ravel-0.4-negative-evidence.json`; -- `ravel-0.4-source-manifest.json`; -- `ravel-0.4-assurance-case.json`; and -- `RAVEL_0_4_RESULTS.md`. +- `ravel_versions/0.4/ravel_0_4.c`; +- `ravel_versions/0.4/RAVEL_0_4_CONTRACT.md`; +- `ravel_versions/0.4/ravel-0.4-preregistration.json`; +- `ravel_versions/0.4/ravel-0.4-raw-observations.json`; +- `ravel_versions/0.4/ravel-0.4-trial-evidence.json`; +- `ravel_versions/0.4/ravel-0.4-negative-evidence.json`; +- `ravel_versions/0.4/ravel-0.4-source-manifest.json`; +- `ravel_versions/0.4/ravel-0.4-assurance-case.json`; and +- `ravel_versions/0.4/RAVEL_0_4_RESULTS.md`. RAVEL 0.4 introduced disjoint training, adaptation, holdout, retention, and planning partitions; canonical checkpoint encoding; complete restored-behavior @@ -98,18 +103,18 @@ the most important 0.4 defects without weakening the frozen evidence boundary? **Primary files:** -- `ravel_0_5.c`; -- `RAVEL_0_5_CONTRACT.md`; -- `ravel-0.5-preregistration.json`; +- `ravel_versions/0.5/ravel_0_5.c`; +- `ravel_versions/0.5/RAVEL_0_5_CONTRACT.md`; +- `ravel_versions/0.5/ravel-0.5-preregistration.json`; - `tools/ravel_0_5_evaluator.py`; - `tools/ravel_0_5_evidence.py`; -- `ravel-0.5-raw-observations.json`; -- `ravel-0.5-trial-evidence.json`; -- `ravel-0.5-negative-evidence.json`; -- `ravel-0.5-source-and-execution-manifest.json`; -- `ravel-0.5-assurance-case.json`; -- `RAVEL_0_5_RESULTS.md`; and -- `RAVEL_0_5_POSTMORTEM.md`. +- `ravel_versions/0.5/ravel-0.5-raw-observations.json`; +- `ravel_versions/0.5/ravel-0.5-trial-evidence.json`; +- `ravel_versions/0.5/ravel-0.5-negative-evidence.json`; +- `ravel_versions/0.5/ravel-0.5-source-and-execution-manifest.json`; +- `ravel_versions/0.5/ravel-0.5-assurance-case.json`; +- `ravel_versions/0.5/RAVEL_0_5_RESULTS.md`; and +- `ravel_versions/0.5/RAVEL_0_5_POSTMORTEM.md`. Mechanism changes included stratified replay, anchored base experts, objective-tested lifecycle changes, normalized residual channels, @@ -136,14 +141,14 @@ separated development and selection lifecycle? **Primary files:** -- `RAVEL_0_6_SCOPE.md`; -- `RAVEL_0_6_PREREGISTRATION.md`; -- `ravel-0.6-preregistration.json`; -- `ravel-0.6-threat-model.json`; -- `ravel-0.6-development-record.json`; -- `ravel-0.6-limitations.md`; +- `ravel_versions/0.6/RAVEL_0_6_SCOPE.md`; +- `ravel_versions/0.6/RAVEL_0_6_PREREGISTRATION.md`; +- `ravel_versions/0.6/ravel-0.6-preregistration.json`; +- `ravel_versions/0.6/ravel-0.6-threat-model.json`; +- `ravel_versions/0.6/ravel-0.6-development-record.json`; +- `ravel_versions/0.6/ravel-0.6-limitations.md`; - `tools/ravel_0_6_seed_candidate.py`; and -- `RAVEL_0_6_NEXT_STEPS.md`. +- `ravel_versions/0.6/RAVEL_0_6_NEXT_STEPS.md`. The epoch was preregistered before implementation. Development, selection, retention, transition-retention, planning, and future-final partitions have diff --git a/RAVEL_0_4_CONTRACT.md b/ravel_versions/0.4/RAVEL_0_4_CONTRACT.md similarity index 100% rename from RAVEL_0_4_CONTRACT.md rename to ravel_versions/0.4/RAVEL_0_4_CONTRACT.md diff --git a/RAVEL_0_4_RESULTS.md b/ravel_versions/0.4/RAVEL_0_4_RESULTS.md similarity index 100% rename from RAVEL_0_4_RESULTS.md rename to ravel_versions/0.4/RAVEL_0_4_RESULTS.md diff --git a/RAVEL_0_4_SCOPE.md b/ravel_versions/0.4/RAVEL_0_4_SCOPE.md similarity index 100% rename from RAVEL_0_4_SCOPE.md rename to ravel_versions/0.4/RAVEL_0_4_SCOPE.md diff --git a/ravel_versions/0.4/path_compat.py b/ravel_versions/0.4/path_compat.py new file mode 100644 index 0000000..e89d3bc --- /dev/null +++ b/ravel_versions/0.4/path_compat.py @@ -0,0 +1,64 @@ +"""Path adapter for the preserved 0.4 manifest protocol.""" + +from __future__ import annotations + +import hashlib +import struct +from pathlib import Path +from typing import Any + + +def physical_path(logical: str, case_root: Path, repository_root: Path) -> Path | None: + candidate = case_root / logical + if candidate.is_file(): + return candidate + if logical.startswith("tools/"): + candidate = repository_root / logical + return candidate if candidate.is_file() else None + return None + + +def build_manifest( + spec_path: Path, case_root: Path, repository_root: Path, digest_module: Any +) -> dict[str, Any]: + spec = digest_module.load_json(spec_path) + digest_module.validate_spec(spec) + entries: list[dict[str, Any]] = [] + for item in spec["ordered_files"]: + logical = item["path"] + absolute = physical_path(logical, case_root, repository_root) + if absolute is None: + raise digest_module.ManifestError(f"listed source file is missing: {logical}") + content = absolute.read_bytes() + entries.append( + { + "order": len(entries), + "role": item["role"], + "path": logical, + "bytes": len(content), + "sha256": hashlib.sha256(content).hexdigest(), + } + ) + framed = hashlib.sha256() + for entry in entries: + logical_bytes = entry["path"].encode("utf-8") + content_path = physical_path(entry["path"], case_root, repository_root) + assert content_path is not None + content = content_path.read_bytes() + framed.update(struct.pack(">I", len(logical_bytes))) + framed.update(logical_bytes) + framed.update(struct.pack(">Q", len(content))) + framed.update(content) + return { + "schema": "ravel-source-manifest/0.4", + "entrypoint": spec["entrypoint"], + "generated_execution_shards": spec["generated_execution_shards"], + "generator_source": None, + "source_provenance": spec["source_provenance"], + "evidence_schema_versions": spec["evidence_schema_versions"], + "digest_algorithm": spec["digest_algorithm"], + "digest_procedure": spec["digest_procedure"], + "ordered_files": entries, + "source_digest": framed.hexdigest(), + "unexpected_execution_shards": [], + } diff --git a/ravel-0.4-assurance-case.json b/ravel_versions/0.4/ravel-0.4-assurance-case.json similarity index 100% rename from ravel-0.4-assurance-case.json rename to ravel_versions/0.4/ravel-0.4-assurance-case.json diff --git a/ravel-0.4-limitations.md b/ravel_versions/0.4/ravel-0.4-limitations.md similarity index 100% rename from ravel-0.4-limitations.md rename to ravel_versions/0.4/ravel-0.4-limitations.md diff --git a/ravel-0.4-negative-evidence.json b/ravel_versions/0.4/ravel-0.4-negative-evidence.json similarity index 100% rename from ravel-0.4-negative-evidence.json rename to ravel_versions/0.4/ravel-0.4-negative-evidence.json diff --git a/ravel-0.4-preregistration.json b/ravel_versions/0.4/ravel-0.4-preregistration.json similarity index 100% rename from ravel-0.4-preregistration.json rename to ravel_versions/0.4/ravel-0.4-preregistration.json diff --git a/ravel-0.4-raw-observations.json b/ravel_versions/0.4/ravel-0.4-raw-observations.json similarity index 100% rename from ravel-0.4-raw-observations.json rename to ravel_versions/0.4/ravel-0.4-raw-observations.json diff --git a/ravel-0.4-runtime-observations.json b/ravel_versions/0.4/ravel-0.4-runtime-observations.json similarity index 100% rename from ravel-0.4-runtime-observations.json rename to ravel_versions/0.4/ravel-0.4-runtime-observations.json diff --git a/ravel-0.4-source-manifest-spec.json b/ravel_versions/0.4/ravel-0.4-source-manifest-spec.json similarity index 100% rename from ravel-0.4-source-manifest-spec.json rename to ravel_versions/0.4/ravel-0.4-source-manifest-spec.json diff --git a/ravel-0.4-source-manifest.json b/ravel_versions/0.4/ravel-0.4-source-manifest.json similarity index 100% rename from ravel-0.4-source-manifest.json rename to ravel_versions/0.4/ravel-0.4-source-manifest.json diff --git a/ravel-0.4-threat-model.json b/ravel_versions/0.4/ravel-0.4-threat-model.json similarity index 100% rename from ravel-0.4-threat-model.json rename to ravel_versions/0.4/ravel-0.4-threat-model.json diff --git a/ravel-0.4-trial-evidence.json b/ravel_versions/0.4/ravel-0.4-trial-evidence.json similarity index 100% rename from ravel-0.4-trial-evidence.json rename to ravel_versions/0.4/ravel-0.4-trial-evidence.json diff --git a/ravel_0_4.c b/ravel_versions/0.4/ravel_0_4.c similarity index 100% rename from ravel_0_4.c rename to ravel_versions/0.4/ravel_0_4.c diff --git a/ravel_versions/0.4/run_evidence.py b/ravel_versions/0.4/run_evidence.py new file mode 100644 index 0000000..283f87e --- /dev/null +++ b/ravel_versions/0.4/run_evidence.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Run the preserved 0.4 evidence utility against its relocated case root.""" + +from __future__ import annotations + +import sys +from pathlib import Path + +CASE_ROOT = Path(__file__).resolve().parent +REPOSITORY_ROOT = CASE_ROOT.parents[1] +sys.path.insert(0, str(REPOSITORY_ROOT / "tools")) + +import ravel_source_digest as digest # noqa: E402 +import ravel_0_4_evidence as evidence # noqa: E402 +from path_compat import build_manifest as compat_build_manifest # noqa: E402 + +digest.CASE_ROOT = CASE_ROOT +digest.build_manifest = lambda spec_path: compat_build_manifest( + spec_path, CASE_ROOT, REPOSITORY_ROOT, digest +) +evidence.CASE_ROOT = CASE_ROOT +evidence.build_manifest = digest.build_manifest +for name in ( + "PREREGISTRATION", + "MANIFEST_SPEC", + "RAW_EVIDENCE", + "TRIAL_EVIDENCE", + "NEGATIVE_EVIDENCE", + "SOURCE_MANIFEST", + "ASSURANCE", + "RESULTS_DOC", + "RUNTIME_EVIDENCE", +): + setattr(evidence, name, CASE_ROOT / getattr(evidence, name).name) + +raise SystemExit(evidence.main()) diff --git a/ravel_versions/0.4/run_source_digest.py b/ravel_versions/0.4/run_source_digest.py new file mode 100644 index 0000000..e1f84a9 --- /dev/null +++ b/ravel_versions/0.4/run_source_digest.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +"""Run the preserved 0.4 digest utility against its relocated case root.""" + +from __future__ import annotations + +import sys +from pathlib import Path + +CASE_ROOT = Path(__file__).resolve().parent +REPOSITORY_ROOT = CASE_ROOT.parents[1] +sys.path.insert(0, str(REPOSITORY_ROOT / "tools")) + +import ravel_source_digest as digest # noqa: E402 +from path_compat import build_manifest as compat_build_manifest # noqa: E402 + +digest.CASE_ROOT = CASE_ROOT +digest.build_manifest = lambda spec_path: compat_build_manifest( + spec_path, CASE_ROOT, REPOSITORY_ROOT, digest +) + +raise SystemExit(digest.main()) diff --git a/ravel_versions/0.5/Makefile b/ravel_versions/0.5/Makefile new file mode 100644 index 0000000..5dcc289 --- /dev/null +++ b/ravel_versions/0.5/Makefile @@ -0,0 +1,218 @@ +CC ?= cc +SAN_CC ?= clang +CFLAGS ?= -std=c11 -O3 -Wall -Wextra -Werror -pedantic +LDLIBS ?= -lm + +.PHONY: test evidence training-test training-evidence training-check unified-test unified-evidence unified-check 0.4-evidence 0.4-check 0.4-manifest-negative-test 0.4-checkpoint-test 0.4-lineage-test 0.4-negative-test 0.4-compiler-matrix 0.4-sanitizers 0.4-runtime 0.5-test 0.5-evidence 0.5-check 0.5-development-gates 0.5-negative-test 0.5-manifest-negative-test 0.5-compiler-matrix 0.5-sanitizers 0.5-runtime 0.5-clean all clean + +test: ravel + ./ravel >/dev/null + +evidence: ravel + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + if ./ravel > "$$tmp"; then \ + mv "$$tmp" evidence-actual.json; \ + else \ + cp "$$tmp" evidence-actual.json; \ + exit 1; \ + fi + +training-test: ravel_train + ./ravel_train >/dev/null + +training-evidence: ravel_train + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + ./ravel_train > "$$tmp"; \ + mv "$$tmp" training-evidence.json + +training-check: ravel_train + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + ./ravel_train > "$$tmp"; \ + diff -u training-evidence.json "$$tmp" + +unified-test: ravel_unified_bin + ./ravel_unified_bin >/dev/null + +unified-evidence: ravel_unified_bin + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + ./ravel_unified_bin > "$$tmp"; \ + mv "$$tmp" unified-evidence.json + +unified-check: ravel_unified_bin + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + if ./ravel_unified_bin > "$$tmp" && diff -u unified-evidence.json "$$tmp"; then \ + rm -f unified-actual.json; \ + else \ + cp "$$tmp" unified-actual.json; \ + exit 1; \ + fi + +0.4-evidence: ravel_0_4_bin + python3 tools/ravel_0_4_evidence.py generate --binary ./ravel_0_4_bin + +0.4-check: ravel_0_4_bin + python3 tools/ravel_0_4_evidence.py verify --binary ./ravel_0_4_bin --diagnostics-dir diagnostics + python3 tools/ravel_source_digest.py verify \ + --spec ravel-0.4-source-manifest-spec.json \ + --manifest ravel-0.4-source-manifest.json \ + --assurance ravel-0.4-assurance-case.json + +0.4-manifest-negative-test: + @tmp=$$(mktemp -d); \ + trap 'rm -rf "$$tmp"' EXIT; \ + cp -a . "$$tmp/ravel"; \ + cd "$$tmp/ravel"; \ + verify='python3 tools/ravel_source_digest.py verify --spec ravel-0.4-source-manifest-spec.json --manifest ravel-0.4-source-manifest.json --assurance ravel-0.4-assurance-case.json'; \ + $$verify >/dev/null; \ + cp RAVEL_0_4_CONTRACT.md contract.saved; \ + printf '\nmutation\n' >> RAVEL_0_4_CONTRACT.md; \ + if $$verify >/dev/null 2>&1; then exit 1; fi; \ + mv contract.saved RAVEL_0_4_CONTRACT.md; \ + cp ravel-0.4-source-manifest.json manifest.saved; \ + python3 -c 'import json; p="ravel-0.4-source-manifest.json"; r=json.load(open(p)); r["ordered_files"].pop(); json.dump(r,open(p,"w"))'; \ + if $$verify >/dev/null 2>&1; then exit 1; fi; \ + cp manifest.saved ravel-0.4-source-manifest.json; \ + python3 -c 'import json; p="ravel-0.4-source-manifest.json"; r=json.load(open(p)); r["ordered_files"][0],r["ordered_files"][1]=r["ordered_files"][1],r["ordered_files"][0]; json.dump(r,open(p,"w"))'; \ + if $$verify >/dev/null 2>&1; then exit 1; fi; \ + cp manifest.saved ravel-0.4-source-manifest.json; \ + mkdir -p ravel_0_4; \ + printf 'unexpected\n' > ravel_0_4/unexpected.inc; \ + if $$verify >/dev/null 2>&1; then exit 1; fi; \ + rm -rf ravel_0_4; \ + cp ravel-0.4-assurance-case.json assurance.saved; \ + python3 -c 'import json; p="ravel-0.4-assurance-case.json"; r=json.load(open(p)); r["implementation"]["source_digest"]="0"*64; json.dump(r,open(p,"w"))'; \ + if $$verify >/dev/null 2>&1; then exit 1; fi; \ + mv assurance.saved ravel-0.4-assurance-case.json + +0.4-checkpoint-test: ravel_0_4_bin + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + ./ravel_0_4_bin > "$$tmp"; \ + python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert all(t["checkpoint_verification"]["complete_behavior_match"] and all(t["checkpoint_verification"]["mutations"].values()) for t in r["trials"])' "$$tmp" + +0.4-lineage-test: ravel_0_4_bin + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + ./ravel_0_4_bin > "$$tmp"; \ + python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert all(all(t["lineage_invariants"].values()) for t in r["trials"])' "$$tmp" + +0.4-negative-test: ravel_0_4_bin + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + ./ravel_0_4_bin > "$$tmp"; \ + python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert all(v["pass"] for v in r["negative_tests"].values())' "$$tmp" + +0.4-compiler-matrix: + @set -eu; \ + for compiler in gcc clang; do \ + if command -v "$$compiler" >/dev/null 2>&1; then \ + for optimization in 0 3; do \ + binary=$$(mktemp); output=$$(mktemp); \ + "$$compiler" -std=c11 "-O$$optimization" -Wall -Wextra -Werror -pedantic ravel_0_4.c -lm -o "$$binary"; \ + "$$binary" > "$$output"; \ + diff -u ravel-0.4-raw-observations.json "$$output"; \ + rm -f "$$binary" "$$output"; \ + done; \ + fi; \ + done + +0.4-sanitizers: + @set -eu; \ + command -v "$(SAN_CC)" >/dev/null 2>&1 || { echo "sanitizer compiler unavailable: $(SAN_CC)" >&2; exit 1; }; \ + binary=$$(mktemp); output=$$(mktemp); \ + trap 'rm -f "$$binary" "$$output"' EXIT; \ + $(SAN_CC) -std=c11 -O1 -g -Wall -Wextra -Werror -pedantic \ + -fsanitize=address,undefined -fno-omit-frame-pointer \ + ravel_0_4.c -lm -o "$$binary"; \ + ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 "$$binary" > "$$output"; \ + diff -u ravel-0.4-raw-observations.json "$$output" + +0.4-runtime: ravel_0_4_bin + python3 tools/ravel_0_4_evidence.py runtime --binary ./ravel_0_4_bin --runs 3 + +0.5-test: ravel_0_5_bin + @tmp=$$(mktemp); \ + trap 'rm -f "$$tmp"' EXIT; \ + ./ravel_0_5_bin --self-test > "$$tmp"; \ + python3 -c 'import json,sys; r=json.load(open(sys.argv[1])); assert r["schema"] == "ravel-self-test-observations/0.5"; assert all(v["observed"] for v in r["fixtures"].values())' "$$tmp" + +0.5-evidence: ravel_0_5_bin + python3 tools/ravel_0_5_evidence.py generate --binary ./ravel_0_5_bin + +0.5-check: ravel_0_5_bin + python3 tools/ravel_0_5_evidence.py verify --binary ./ravel_0_5_bin --diagnostics-dir diagnostics-0.5 + python3 tools/ravel_0_5_source_digest.py verify \ + --spec ravel-0.5-source-manifest-spec.json \ + --manifest ravel-0.5-source-and-execution-manifest.json \ + --assurance ravel-0.5-assurance-case.json + +0.5-development-gates: + python3 tools/ravel_0_5_evidence.py development-gates + +0.5-negative-test: ravel_0_5_bin + $(MAKE) 0.5-test + python3 tools/ravel_0_5_evidence.py mutation-tests + python3 -c 'import json; r=json.load(open("ravel-0.5-negative-evidence.json")); assert r["all_negative_tests_pass"]; assert len(r["tests"]) == len(set(r["tests"]))' + +0.5-manifest-negative-test: + python3 tools/ravel_0_5_evidence.py manifest-negative-tests + +0.5-compiler-matrix: + @set -eu; \ + for compiler in gcc clang; do \ + if command -v "$$compiler" >/dev/null 2>&1; then \ + for optimization in 0 3; do \ + binary=$$(mktemp); \ + trap 'rm -f "$$binary"' EXIT; \ + "$$compiler" -std=c11 "-O$$optimization" -Wall -Wextra -Werror -pedantic ravel_0_5.c -lm -o "$$binary"; \ + python3 tools/ravel_0_5_evidence.py verify --binary "$$binary" --diagnostics-dir diagnostics-0.5; \ + rm -f "$$binary"; \ + trap - EXIT; \ + done; \ + fi; \ + done + +0.5-sanitizers: + @set -eu; \ + command -v "$(SAN_CC)" >/dev/null 2>&1 || { echo "sanitizer compiler unavailable: $(SAN_CC)" >&2; exit 1; }; \ + binary=$$(mktemp); \ + trap 'rm -f "$$binary"' EXIT; \ + $(SAN_CC) -std=c11 -O1 -g -Wall -Wextra -Werror -pedantic \ + -fsanitize=address,undefined -fno-omit-frame-pointer \ + ravel_0_5.c -lm -o "$$binary"; \ + ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 \ + python3 tools/ravel_0_5_evidence.py verify --binary "$$binary" --diagnostics-dir diagnostics-0.5 + +0.5-runtime: ravel_0_5_bin + python3 tools/ravel_0_5_evidence.py runtime --binary ./ravel_0_5_bin --runs 3 + +0.5-clean: + rm -f ravel_0_5_bin + rm -rf diagnostics-0.5 + +all: test training-check unified-check 0.4-check 0.5-check + +ravel: ravel.c + $(CC) $(CFLAGS) $< -o $@ + +ravel_train: ravel_train.c + $(CC) $(CFLAGS) $< $(LDLIBS) -o $@ + +ravel_unified_bin: ravel_unified.c ravel_unified/00_core.inc ravel_unified/10_route.inc ravel_unified/20_train.inc ravel_unified/30_eval.inc + $(CC) $(CFLAGS) ravel_unified.c $(LDLIBS) -o $@ + +ravel_0_4_bin: ravel_0_4.c + $(CC) $(CFLAGS) ravel_0_4.c $(LDLIBS) -o $@ + +ravel_0_5_bin: ravel_0_5.c + $(CC) $(CFLAGS) ravel_0_5.c $(LDLIBS) -o $@ + +clean: + rm -f ravel ravel_train ravel_unified_bin ravel_0_4_bin ravel_0_5_bin + rm -f evidence-actual.json unified-actual.json ravel-unified-checkpoint.bin ravel-0.4-checkpoint.bin + rm -rf diagnostics diff --git a/RAVEL_0_5_CONTRACT.md b/ravel_versions/0.5/RAVEL_0_5_CONTRACT.md similarity index 100% rename from RAVEL_0_5_CONTRACT.md rename to ravel_versions/0.5/RAVEL_0_5_CONTRACT.md diff --git a/RAVEL_0_5_POSTMORTEM.md b/ravel_versions/0.5/RAVEL_0_5_POSTMORTEM.md similarity index 100% rename from RAVEL_0_5_POSTMORTEM.md rename to ravel_versions/0.5/RAVEL_0_5_POSTMORTEM.md diff --git a/RAVEL_0_5_RESULTS.md b/ravel_versions/0.5/RAVEL_0_5_RESULTS.md similarity index 100% rename from RAVEL_0_5_RESULTS.md rename to ravel_versions/0.5/RAVEL_0_5_RESULTS.md diff --git a/RAVEL_0_5_SCOPE.md b/ravel_versions/0.5/RAVEL_0_5_SCOPE.md similarity index 100% rename from RAVEL_0_5_SCOPE.md rename to ravel_versions/0.5/RAVEL_0_5_SCOPE.md diff --git a/ravel-0.5-assurance-case.json b/ravel_versions/0.5/ravel-0.5-assurance-case.json similarity index 100% rename from ravel-0.5-assurance-case.json rename to ravel_versions/0.5/ravel-0.5-assurance-case.json diff --git a/ravel-0.5-development-corpus.json b/ravel_versions/0.5/ravel-0.5-development-corpus.json similarity index 100% rename from ravel-0.5-development-corpus.json rename to ravel_versions/0.5/ravel-0.5-development-corpus.json diff --git a/ravel-0.5-limitations.md b/ravel_versions/0.5/ravel-0.5-limitations.md similarity index 100% rename from ravel-0.5-limitations.md rename to ravel_versions/0.5/ravel-0.5-limitations.md diff --git a/ravel-0.5-negative-evidence.json b/ravel_versions/0.5/ravel-0.5-negative-evidence.json similarity index 100% rename from ravel-0.5-negative-evidence.json rename to ravel_versions/0.5/ravel-0.5-negative-evidence.json diff --git a/ravel-0.5-preregistration.json b/ravel_versions/0.5/ravel-0.5-preregistration.json similarity index 100% rename from ravel-0.5-preregistration.json rename to ravel_versions/0.5/ravel-0.5-preregistration.json diff --git a/ravel-0.5-raw-observations.json b/ravel_versions/0.5/ravel-0.5-raw-observations.json similarity index 100% rename from ravel-0.5-raw-observations.json rename to ravel_versions/0.5/ravel-0.5-raw-observations.json diff --git a/ravel-0.5-runtime-observations.json b/ravel_versions/0.5/ravel-0.5-runtime-observations.json similarity index 100% rename from ravel-0.5-runtime-observations.json rename to ravel_versions/0.5/ravel-0.5-runtime-observations.json diff --git a/ravel-0.5-source-and-execution-manifest.json b/ravel_versions/0.5/ravel-0.5-source-and-execution-manifest.json similarity index 100% rename from ravel-0.5-source-and-execution-manifest.json rename to ravel_versions/0.5/ravel-0.5-source-and-execution-manifest.json diff --git a/ravel-0.5-source-manifest-spec.json b/ravel_versions/0.5/ravel-0.5-source-manifest-spec.json similarity index 100% rename from ravel-0.5-source-manifest-spec.json rename to ravel_versions/0.5/ravel-0.5-source-manifest-spec.json diff --git a/ravel-0.5-threat-model.json b/ravel_versions/0.5/ravel-0.5-threat-model.json similarity index 100% rename from ravel-0.5-threat-model.json rename to ravel_versions/0.5/ravel-0.5-threat-model.json diff --git a/ravel-0.5-trial-evidence.json b/ravel_versions/0.5/ravel-0.5-trial-evidence.json similarity index 100% rename from ravel-0.5-trial-evidence.json rename to ravel_versions/0.5/ravel-0.5-trial-evidence.json diff --git a/ravel_0_5.c b/ravel_versions/0.5/ravel_0_5.c similarity index 100% rename from ravel_0_5.c rename to ravel_versions/0.5/ravel_0_5.c diff --git a/ravel_versions/0.5/run_evidence.py b/ravel_versions/0.5/run_evidence.py new file mode 100644 index 0000000..0b60516 --- /dev/null +++ b/ravel_versions/0.5/run_evidence.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +"""Run preserved 0.5 tooling with historical logical-path compatibility.""" + +from __future__ import annotations + +import hashlib +import struct +import sys +from pathlib import Path +from typing import Any + +CASE_ROOT = Path(__file__).resolve().parent +REPOSITORY_ROOT = CASE_ROOT.parents[1] +sys.path.insert(0, str(REPOSITORY_ROOT / "tools")) + +import ravel_0_5_evidence as evidence # noqa: E402 +import ravel_0_5_source_digest as source_digest # noqa: E402 + +source_digest.CASE_ROOT = CASE_ROOT +source_digest.REPOSITORY_ROOT = REPOSITORY_ROOT +evidence.CASE_ROOT = CASE_ROOT +evidence.TOOL_ROOT = REPOSITORY_ROOT / "tools" +for name in ( + "PREREGISTRATION", + "MANIFEST_SPEC", + "RAW", + "TRIAL", + "NEGATIVE", + "MANIFEST", + "ASSURANCE", + "RESULTS", + "RUNTIME", +): + setattr(evidence, name, CASE_ROOT / getattr(evidence, name).name) +evidence.PACKAGE_PATHS = ( + evidence.RAW, + evidence.TRIAL, + evidence.NEGATIVE, + evidence.MANIFEST, + evidence.ASSURANCE, + evidence.RESULTS, +) + + +def physical_path(logical: str, repository_root: Path) -> Path | None: + """Resolve a historical manifest path without changing its logical spelling.""" + + if logical == "Makefile" and repository_root == REPOSITORY_ROOT: + return None + direct = repository_root / logical + if direct.is_file(): + return direct + prefix = "case-studies/ravel/" + if logical.startswith(prefix): + relative = logical.removeprefix(prefix) + candidate = ( + REPOSITORY_ROOT / "tools" / relative.removeprefix("tools/") + if relative.startswith("tools/") + else CASE_ROOT / relative + ) + return candidate if candidate.is_file() else None + return direct if direct.is_file() else None + + +def compat_build_manifest( + spec_path: Path, repository_root: Path | None = None +) -> dict[str, Any]: + root = REPOSITORY_ROOT if repository_root is None else repository_root + spec = source_digest.load_json(spec_path) + source_digest.validate_spec(spec) + declared = set(spec["generated_execution_shards"]) | set( + spec["maintained_execution_sources"] + ) + discovered: set[str] = set() + for pattern in spec.get("execution_source_discovery_globs", []): + prefix = "case-studies/ravel/" + if pattern.startswith(prefix): + for path in CASE_ROOT.glob(pattern.removeprefix(prefix)): + if path.is_file(): + discovered.add(prefix + path.relative_to(CASE_ROOT).as_posix()) + else: + for path in root.glob(pattern): + if path.is_file(): + discovered.add(path.relative_to(root).as_posix()) + unexpected = sorted(discovered - declared) + omitted = sorted(declared - discovered) + if unexpected: + raise source_digest.ManifestError( + f"unexpected execution shard outside manifest: {unexpected}" + ) + if omitted: + raise source_digest.ManifestError( + f"declared execution shard is missing: {omitted}" + ) + + entries: list[dict[str, Any]] = [] + for item in spec["ordered_files"]: + logical = item["path"] + absolute = physical_path(logical, root) + if absolute is None: + raise source_digest.ManifestError( + f"listed source file is missing: {logical}" + ) + content = absolute.read_bytes() + entries.append( + { + "order": len(entries), + "role": item["role"], + "path": logical, + "bytes": len(content), + "sha256": hashlib.sha256(content).hexdigest(), + } + ) + digest = hashlib.sha256() + for entry in entries: + logical_bytes = entry["path"].encode("utf-8") + content_path = physical_path(entry["path"], root) + assert content_path is not None + content = content_path.read_bytes() + digest.update(struct.pack(">I", len(logical_bytes))) + digest.update(logical_bytes) + digest.update(struct.pack(">Q", len(content))) + digest.update(content) + return { + "schema": "ravel-source-and-execution-manifest/0.5", + "entrypoint": spec["entrypoint"], + "maintained_execution_sources": spec["maintained_execution_sources"], + "generated_execution_shards": spec["generated_execution_shards"], + "generator_source": None, + "source_provenance": spec["source_provenance"], + "build_configuration": spec["build_configuration"], + "checkpoint_schema": spec["checkpoint_schema"], + "evidence_schema_versions": spec["evidence_schema_versions"], + "digest_algorithm": spec["digest_algorithm"], + "digest_procedure": spec["digest_procedure"], + "ordered_files": entries, + "source_digest": digest.hexdigest(), + "unexpected_execution_shards": [], + } + + +evidence.build_manifest = compat_build_manifest + +raise SystemExit(evidence.main()) diff --git a/RAVEL_0_6_NEXT_STEPS.md b/ravel_versions/0.6/RAVEL_0_6_NEXT_STEPS.md similarity index 100% rename from RAVEL_0_6_NEXT_STEPS.md rename to ravel_versions/0.6/RAVEL_0_6_NEXT_STEPS.md diff --git a/RAVEL_0_6_PREREGISTRATION.md b/ravel_versions/0.6/RAVEL_0_6_PREREGISTRATION.md similarity index 100% rename from RAVEL_0_6_PREREGISTRATION.md rename to ravel_versions/0.6/RAVEL_0_6_PREREGISTRATION.md diff --git a/RAVEL_0_6_SCOPE.md b/ravel_versions/0.6/RAVEL_0_6_SCOPE.md similarity index 100% rename from RAVEL_0_6_SCOPE.md rename to ravel_versions/0.6/RAVEL_0_6_SCOPE.md diff --git a/ravel-0.6-development-record.json b/ravel_versions/0.6/ravel-0.6-development-record.json similarity index 100% rename from ravel-0.6-development-record.json rename to ravel_versions/0.6/ravel-0.6-development-record.json diff --git a/ravel-0.6-limitations.md b/ravel_versions/0.6/ravel-0.6-limitations.md similarity index 100% rename from ravel-0.6-limitations.md rename to ravel_versions/0.6/ravel-0.6-limitations.md diff --git a/ravel-0.6-preregistration.json b/ravel_versions/0.6/ravel-0.6-preregistration.json similarity index 100% rename from ravel-0.6-preregistration.json rename to ravel_versions/0.6/ravel-0.6-preregistration.json diff --git a/ravel-0.6-preregistration.schema.json b/ravel_versions/0.6/ravel-0.6-preregistration.schema.json similarity index 100% rename from ravel-0.6-preregistration.schema.json rename to ravel_versions/0.6/ravel-0.6-preregistration.schema.json diff --git a/ravel-0.6-threat-model.json b/ravel_versions/0.6/ravel-0.6-threat-model.json similarity index 100% rename from ravel-0.6-threat-model.json rename to ravel_versions/0.6/ravel-0.6-threat-model.json diff --git a/CONTRACT.md b/ravel_versions/baseline/CONTRACT.md similarity index 100% rename from CONTRACT.md rename to ravel_versions/baseline/CONTRACT.md diff --git a/evidence.json b/ravel_versions/baseline/evidence.json similarity index 100% rename from evidence.json rename to ravel_versions/baseline/evidence.json diff --git a/ravel.c b/ravel_versions/baseline/ravel.c similarity index 100% rename from ravel.c rename to ravel_versions/baseline/ravel.c diff --git a/TRAINING_CONTRACT.md b/ravel_versions/training/TRAINING_CONTRACT.md similarity index 100% rename from TRAINING_CONTRACT.md rename to ravel_versions/training/TRAINING_CONTRACT.md diff --git a/ravel_train.c b/ravel_versions/training/ravel_train.c similarity index 100% rename from ravel_train.c rename to ravel_versions/training/ravel_train.c diff --git a/training-assurance-case.json b/ravel_versions/training/training-assurance-case.json similarity index 100% rename from training-assurance-case.json rename to ravel_versions/training/training-assurance-case.json diff --git a/training-evidence.json b/ravel_versions/training/training-evidence.json similarity index 100% rename from training-evidence.json rename to ravel_versions/training/training-evidence.json diff --git a/training-preregistration.json b/ravel_versions/training/training-preregistration.json similarity index 100% rename from training-preregistration.json rename to ravel_versions/training/training-preregistration.json diff --git a/training-threat-model.json b/ravel_versions/training/training-threat-model.json similarity index 100% rename from training-threat-model.json rename to ravel_versions/training/training-threat-model.json diff --git a/UNIFIED_CONTRACT.md b/ravel_versions/unified/UNIFIED_CONTRACT.md similarity index 100% rename from UNIFIED_CONTRACT.md rename to ravel_versions/unified/UNIFIED_CONTRACT.md diff --git a/ravel_unified.c b/ravel_versions/unified/ravel_unified.c similarity index 100% rename from ravel_unified.c rename to ravel_versions/unified/ravel_unified.c diff --git a/ravel_unified/00_core.inc b/ravel_versions/unified/ravel_unified/00_core.inc similarity index 100% rename from ravel_unified/00_core.inc rename to ravel_versions/unified/ravel_unified/00_core.inc diff --git a/ravel_unified/10_route.inc b/ravel_versions/unified/ravel_unified/10_route.inc similarity index 100% rename from ravel_unified/10_route.inc rename to ravel_versions/unified/ravel_unified/10_route.inc diff --git a/ravel_unified/20_train.inc b/ravel_versions/unified/ravel_unified/20_train.inc similarity index 100% rename from ravel_unified/20_train.inc rename to ravel_versions/unified/ravel_unified/20_train.inc diff --git a/ravel_unified/30_eval.inc b/ravel_versions/unified/ravel_unified/30_eval.inc similarity index 100% rename from ravel_unified/30_eval.inc rename to ravel_versions/unified/ravel_unified/30_eval.inc diff --git a/unified-assurance-case.json b/ravel_versions/unified/unified-assurance-case.json similarity index 100% rename from unified-assurance-case.json rename to ravel_versions/unified/unified-assurance-case.json diff --git a/unified-evidence.json b/ravel_versions/unified/unified-evidence.json similarity index 100% rename from unified-evidence.json rename to ravel_versions/unified/unified-evidence.json diff --git a/unified-preregistration.json b/ravel_versions/unified/unified-preregistration.json similarity index 100% rename from unified-preregistration.json rename to ravel_versions/unified/unified-preregistration.json diff --git a/unified-threat-model.json b/ravel_versions/unified/unified-threat-model.json similarity index 100% rename from unified-threat-model.json rename to ravel_versions/unified/unified-threat-model.json diff --git a/tools/README.md b/tools/README.md index 4096709..ed95679 100644 --- a/tools/README.md +++ b/tools/README.md @@ -4,6 +4,13 @@ The scripts in this directory build, verify, mutate, digest, and summarize RAVEL evidence. They are support tools, not automatic sources of independent custody, organizational independence, or promotion authority. +The preserved 0.4 and 0.5 modules retain their original case-root assumptions +and bytes. Run `ravel_versions/0.4/run_evidence.py`, +`ravel_versions/0.4/run_source_digest.py`, or +`ravel_versions/0.5/run_evidence.py` through the root Makefile for the relocated +layout; those small runners provide path compatibility without rewriting frozen +modules or historical logical paths. + ## Tool categories | Tool | Role | @@ -89,7 +96,7 @@ separation alone is not organizational independence or protected evaluation. The current candidate-001 corrections expand planning traversal to all declared transition slots and remove inherited empirical support from adaptation births. -See `../RAVEL_0_6_NEXT_STEPS.md` for the remaining lifecycle and evidence work. +See `../ravel_versions/0.6/RAVEL_0_6_NEXT_STEPS.md` for the remaining lifecycle and evidence work. ## Adding or changing a tool diff --git a/tools/__pycache__/ravel_0_5_evaluator.cpython-314.pyc b/tools/__pycache__/ravel_0_5_evaluator.cpython-314.pyc deleted file mode 100644 index 48894572d52b326c4a7a2002c46f65f8d34d35e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54893 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 Y|Ai~?;g#=)6jx)8ZUj4-)*N;J7i88lCjbBd diff --git a/tools/__pycache__/ravel_source_digest.cpython-314.pyc b/tools/__pycache__/ravel_source_digest.cpython-314.pyc deleted file mode 100644 index 186851d54b824d7042d8e1c46ba65b70f9d384e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13943 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 I(?o{yzd_{tB>(^b diff --git a/tools/ravel_0_6_seed_candidate.py b/tools/ravel_0_6_seed_candidate.py index f0b25df..910efe6 100644 --- a/tools/ravel_0_6_seed_candidate.py +++ b/tools/ravel_0_6_seed_candidate.py @@ -22,7 +22,7 @@ from pathlib import Path RAVEL_DIR = Path(__file__).resolve().parents[1] -FROZEN_SOURCE = RAVEL_DIR / "ravel_0_5.c" +FROZEN_SOURCE = RAVEL_DIR / "ravel_versions/0.5/ravel_0_5.c" FROZEN_SOURCE_SHA256 = "1a8466ea1805811873c461fb891aaeaec18f6c9e7491b5ea7bd09bf698be102d" OLD_SEED_FUNCTION = """\