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 4889457..0000000 Binary files a/tools/__pycache__/ravel_0_5_evaluator.cpython-314.pyc and /dev/null differ diff --git a/tools/__pycache__/ravel_0_5_source_digest.cpython-314.pyc b/tools/__pycache__/ravel_0_5_source_digest.cpython-314.pyc deleted file mode 100644 index aaa4211..0000000 Binary files a/tools/__pycache__/ravel_0_5_source_digest.cpython-314.pyc and /dev/null differ 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 186851d..0000000 Binary files a/tools/__pycache__/ravel_source_digest.cpython-314.pyc and /dev/null differ 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 = """\