412 lines
25 KiB
Python
412 lines
25 KiB
Python
"""Seal a descriptive laboratory audit, including incomplete and failed runs.
|
||
|
||
Run this with the frozen scientific environment, not the isolated Brian2 venv.
|
||
No simulation, parameter selection, candidate promotion or old-artifact write occurs.
|
||
"""
|
||
from datetime import datetime, timezone
|
||
import json
|
||
import math
|
||
from pathlib import Path
|
||
import sys
|
||
import traceback
|
||
|
||
import numpy as np
|
||
import pandas as pd
|
||
|
||
from context import CFG, EXP, MODEL, ROOT, check_prereg, digest, save, source_hashes
|
||
from prepare import frozen_integrity
|
||
|
||
|
||
UNIT_NAMES = ("zero", "weak_excitation", "inhibition", "refractory_boundary",
|
||
"equal_threshold", "above_threshold", "nonzero_g_reset", "delay_18")
|
||
EXCLUDED_PARTS = {".venv", "__pycache__"}
|
||
SEAL_NAMES = {"manifest.json", "checksums.sha256"}
|
||
|
||
|
||
def read_json(path):
|
||
with Path(path).open(encoding="utf-8") as stream:
|
||
return json.load(stream, parse_constant=lambda value: (_ for _ in ()).throw(
|
||
ValueError("Nonfinite JSON number: " + value)))
|
||
|
||
|
||
def exception_record(error):
|
||
return {"type": type(error).__name__, "message": str(error),
|
||
"traceback": traceback.format_exc()}
|
||
|
||
|
||
def attempt(records, name, function):
|
||
"""Never let an earlier failed arm hide subsequent available evidence."""
|
||
try:
|
||
detail = function()
|
||
if not isinstance(detail, dict) or type(detail.get("pass")) is not bool:
|
||
raise ValueError("Check must provide an explicit Boolean pass")
|
||
item = {"name": name, **detail}
|
||
except Exception as error:
|
||
item = {"name": name, "pass": False, "error": exception_record(error)}
|
||
records.append(item)
|
||
return item
|
||
|
||
|
||
def require(condition, message):
|
||
if not condition:
|
||
raise ValueError(message)
|
||
|
||
|
||
def load_trace(directory, expected_nodes, steps, cfg, seed_node, natural_events=False):
|
||
events = pd.read_csv(directory / "events.csv", dtype={"step": "int64", "neuron_idx": "int64"})
|
||
require(list(events.columns) == ["step", "neuron_idx"], "Unexpected event columns")
|
||
for key in ("step", "neuron_idx"):
|
||
values = events[key].to_numpy()
|
||
require(np.isfinite(values).all() and np.equal(values, np.floor(values)).all(),
|
||
"Nonfinite or nonintegral event field: " + key)
|
||
ticks = events.step.to_numpy(np.int64)
|
||
nodes = events.neuron_idx.to_numpy(np.int64)
|
||
require(bool(np.all((ticks >= 0) & (ticks < steps))), "Event outside trial")
|
||
require(bool(np.all(np.diff(ticks) >= 0)), "Events not time ordered")
|
||
require(not events.duplicated().any(), "Duplicate event at one neuron/timestep")
|
||
require(bool(np.isin(nodes, expected_nodes).all()), "Event identity outside motif")
|
||
with np.load(directory / "state.npz", allow_pickle=False) as stored:
|
||
state = {key: stored[key].copy() for key in stored.files}
|
||
require(np.array_equal(state["nodes"], expected_nodes), "State neuron order differs")
|
||
history = state["history"]
|
||
require(history.shape == (steps, 3, len(expected_nodes)), "Incomplete state history")
|
||
require(all(np.isfinite(value).all() for value in state.values()), "Nonfinite state")
|
||
actual_counts = np.array([np.count_nonzero(nodes == node) for node in expected_nodes])
|
||
require(np.array_equal(state["counts"], actual_counts), "Counts disagree with raw events")
|
||
for index, key in enumerate(("v", "g", "ref")):
|
||
require(np.array_equal(state[key], history[-1, index]),
|
||
"Final state disagrees with history: " + key)
|
||
if seed_node is None and not natural_events:
|
||
require(len(ticks) == 0, "No-input control emitted a spike")
|
||
elif seed_node is not None:
|
||
require(np.array_equal(nodes[ticks == 0], [seed_node]),
|
||
"Declared initial seed event missing or duplicated")
|
||
late = ticks >= round(cfg["late_start_ms"] / cfg["dt_ms"])
|
||
per_node = [{"neuron_idx": int(node), "spikes": int(actual_counts[index]),
|
||
"late_spikes": int(np.count_nonzero(late & (nodes == node))),
|
||
"last_ms": float(ticks[nodes == node][-1] * cfg["dt_ms"])
|
||
if actual_counts[index] else None}
|
||
for index, node in enumerate(expected_nodes)]
|
||
return {"step": ticks, "neuron_idx": nodes, **state}, per_node
|
||
|
||
|
||
def compare_raw(actual, expected, tolerance):
|
||
require(math.isfinite(tolerance) and tolerance >= 0, "Invalid preregistered tolerance")
|
||
a = np.asarray(actual["history"], np.float64)
|
||
b = np.asarray(expected["history"], np.float64)
|
||
require(a.shape == b.shape and a.size > 0, "Incomplete comparison trajectories")
|
||
require(np.isfinite(a).all() and np.isfinite(b).all(), "Nonfinite comparison trajectory")
|
||
error = np.abs(a[:, :2] - b[:, :2])
|
||
exact_events = bool(np.array_equal(actual["step"], expected["step"]) and
|
||
np.array_equal(actual["neuron_idx"], expected["neuron_idx"]))
|
||
first = None
|
||
if not exact_events:
|
||
for step in range(len(a)):
|
||
aa = actual["neuron_idx"][actual["step"] == step]
|
||
bb = expected["neuron_idx"][expected["step"] == step]
|
||
if not np.array_equal(aa, bb):
|
||
first = step
|
||
break
|
||
prefix = error if first is None else error[:first]
|
||
reference_exact = bool(np.array_equal(a[:, 2], b[:, 2]))
|
||
count_exact = bool(np.array_equal(actual["counts"], expected["counts"]))
|
||
maximum = float(error.max())
|
||
return {"exact_events": exact_events, "exact_counts": count_exact,
|
||
"ref_exact": reference_exact, "max_abs_mv": maximum,
|
||
"mean_abs_mv": float(error.mean()),
|
||
"same_event_prefix_max_abs_mv": float(prefix.max()) if prefix.size else None,
|
||
"first_event_divergence_step": first, "tolerance_mv": tolerance,
|
||
"pass_oracle": exact_events and count_exact and reference_exact and maximum <= tolerance}
|
||
|
||
|
||
def comparison_record_matches(raw, stored):
|
||
"""Only descriptive mean reduction may differ between scientific NumPy builds."""
|
||
if set(raw) != set(stored):
|
||
return False
|
||
return all(math.isclose(raw[key], stored[key], rel_tol=0, abs_tol=1e-12)
|
||
if key == "mean_abs_mv" else raw[key] == stored[key] for key in raw)
|
||
|
||
|
||
def motif_nodes(cfg, motif):
|
||
with np.load(ROOT / cfg["prior_experiment"] / "motifs" / (motif + "-state.npz"),
|
||
allow_pickle=False) as prior:
|
||
return prior["nodes"].copy()
|
||
|
||
|
||
def check_summary_rows(table, motif, policy, precision, per_node):
|
||
part = table[(table.motif == motif) & (table.policy == policy) &
|
||
(table.precision == precision)]
|
||
require(len(part) == len(per_node) and not part.neuron_idx.duplicated().any(),
|
||
"Missing/duplicate per-neuron summary rows")
|
||
require(set(part.neuron_idx) == {row["neuron_idx"] for row in per_node},
|
||
"Summary neuron identities differ")
|
||
indexed = part.set_index("neuron_idx")
|
||
for row in per_node:
|
||
current = indexed.loc[row["neuron_idx"]]
|
||
require(current.spikes == row["spikes"] and current.late_spikes == row["late_spikes"],
|
||
"Summary spike counts disagree with raw events")
|
||
last = current.last_ms
|
||
require(pd.isna(last) if row["last_ms"] is None else last == row["last_ms"],
|
||
"Summary last-spike time disagrees with raw events")
|
||
|
||
|
||
def seal(root):
|
||
require(not any((root / name).exists() for name in SEAL_NAMES),
|
||
"Refusing to overwrite an existing seal: " + str(root))
|
||
files = []
|
||
for path in sorted(root.rglob("*")):
|
||
relative = path.relative_to(root)
|
||
if EXCLUDED_PARTS.intersection(relative.parts):
|
||
continue
|
||
require(not path.is_symlink(), "Unsealed symlink not permitted: " + str(path))
|
||
if not path.is_file() or (len(relative.parts) == 1 and path.name in SEAL_NAMES):
|
||
continue
|
||
files.append({"path": relative.as_posix(), "bytes": path.stat().st_size,
|
||
"sha256": digest(path)})
|
||
require(bool(files), "Refusing empty artifact manifest")
|
||
manifest = {"schema": "sha256-artifact-manifest-v1", "root": str(root),
|
||
"created_utc": datetime.now(timezone.utc).isoformat(),
|
||
"excluded_directory_names": sorted(EXCLUDED_PARTS),
|
||
"self_hash_policy": "Manifest lists payload files; checksums also hashes manifest; neither hashes checksums.",
|
||
"files": files}
|
||
save(root / "manifest.json", manifest)
|
||
checksum_rows = files + [{"path": "manifest.json", "sha256": digest(root / "manifest.json")}]
|
||
with (root / "checksums.sha256").open("x", encoding="utf-8", newline="\n") as stream:
|
||
for row in checksum_rows:
|
||
stream.write(row["sha256"] + " " + row["path"] + "\n")
|
||
for row in checksum_rows:
|
||
require(digest(root / row["path"]) == row["sha256"],
|
||
"Artifact changed while sealing: " + row["path"])
|
||
|
||
|
||
def main():
|
||
outputs = [EXP / "audit/finalize-start.json", EXP / "audit/final-summary.json",
|
||
EXP / "regression/old-integrity-after.json", EXP / "regression/preregistration-after.json",
|
||
EXP / "REPORT.md"] + [root / name for root in (MODEL, EXP) for name in SEAL_NAMES]
|
||
require(not any(path.exists() for path in outputs), "Refusing reused finalization outputs")
|
||
save(EXP / "audit/finalize-start.json", {"timestamp_utc": datetime.now(timezone.utc).isoformat(),
|
||
"python": sys.version, "executable": sys.executable, "learning": False,
|
||
"whole_brain_alternative_run": False})
|
||
checks = []
|
||
prereg = attempt(checks, "preregistration", lambda: {"pass": True, "record": check_prereg()})
|
||
if prereg["pass"]:
|
||
cfg = prereg["record"]["config"]
|
||
else:
|
||
# Read the sealed declaration for descriptive recovery, never bless source drift.
|
||
try:
|
||
cfg = read_json(EXP / "protocol/preregistered.json")["config"]
|
||
except Exception:
|
||
cfg = CFG
|
||
integrity = attempt(checks, "old_frozen_integrity_after", lambda: {
|
||
"pass": True, "results": frozen_integrity()})
|
||
save(EXP / "regression/old-integrity-after.json", integrity)
|
||
|
||
def completed():
|
||
record = read_json(EXP / "audit/run-complete.json")
|
||
require(record.get("learning_achieved") is False and
|
||
record.get("whole_brain_alternative_run") is False, "Run scope inconsistent")
|
||
require(record.get("author_original_source_sha256") == digest(EXP / "external-resources/model.py"),
|
||
"Author source hash disagrees with run-complete record")
|
||
return {"pass": record.get("all_author_oracle_comparisons_pass") is True and
|
||
record.get("all_frozen_components_match_archive") is True, "record": record}
|
||
run_complete = attempt(checks, "run_complete", completed)
|
||
|
||
def frozen_five_check():
|
||
record = read_json(EXP / "regression/frozen-five.json")
|
||
trials = record.get("trials", [])
|
||
require(len(trials) == 5 and len({row["trial"] for row in trials}) == 5,
|
||
"Exactly five distinct frozen reference trials are required")
|
||
required = {"step", "neuron_idx", "counts", "v", "g"}
|
||
exact = all(set(row.get("exact", {})) == required and
|
||
all(value is True for value in row["exact"].values()) for row in trials)
|
||
return {"pass": record.get("pass_all") is True and exact, "record": record,
|
||
"scope": "Old frozen runtime regression only, not a new-model dynamics gate."}
|
||
frozen_five = attempt(checks, "frozen_five_gpu_references", frozen_five_check)
|
||
|
||
def interface_check():
|
||
record = read_json(EXP / "oracle/poi-interface/audit.json")
|
||
flags = record.get("checks", {})
|
||
require(isinstance(flags, dict) and bool(flags), "Empty Poisson interface audit")
|
||
require(record.get("author_sha256") == digest(EXP / "external-resources/model.py"),
|
||
"Poisson audit source hash differs")
|
||
require(record.get("simulation_duration_ms") == 0 and
|
||
record.get("stochastic_time_steps") == 0 and
|
||
record.get("random_realization_tested") is False and
|
||
record.get("common_seed_experiment") is False, "Poisson audit scope differs")
|
||
for name, expected in record.get("input_hashes", {}).items():
|
||
require(digest(EXP / "oracle/poi-interface" / name) == expected,
|
||
"Poisson fixture input changed: " + name)
|
||
return {"pass": record.get("gate") is True and all(value is True for value in flags.values()),
|
||
"record": record, "scope": "Compile-time interface audit; no Poisson realization."}
|
||
interface = attempt(checks, "author_poi_compile_only", interface_check)
|
||
outcomes = []
|
||
components = []
|
||
steps = round(cfg["duration_ms"] / cfg["dt_ms"])
|
||
for motif in cfg["motifs"]:
|
||
for policy in cfg["component_policies"]:
|
||
def component_check(motif=motif, policy=policy):
|
||
nodes = motif_nodes(cfg, motif)
|
||
raw, per_node = load_trace(EXP / "components" / (motif + "-" + policy), nodes,
|
||
steps, cfg, None if motif == "no_input" else cfg["seed_node"])
|
||
outcomes.append({"motif": motif, "policy": policy, "precision": "float32",
|
||
"neurons": per_node, "activity_is_not_a_validation_gate": True})
|
||
table = pd.read_csv(EXP / "components/summary.csv", float_precision="round_trip")
|
||
check_summary_rows(table, motif, policy, "float32", per_node)
|
||
if policy == "frozen":
|
||
prior_dir = ROOT / cfg["prior_experiment"] / "motifs"
|
||
old_events = pd.read_parquet(prior_dir / (motif + "-events.parquet"))
|
||
require(np.array_equal(raw["step"], old_events.step) and
|
||
np.array_equal(raw["neuron_idx"], old_events.neuron_idx),
|
||
"Frozen events disagree with 4AC")
|
||
with np.load(prior_dir / (motif + "-state.npz"), allow_pickle=False) as old:
|
||
require(all(np.array_equal(old[key], raw[key]) for key in old.files),
|
||
"Frozen states disagree with 4AC")
|
||
return {"pass": True, "raw_and_summary_consistent": True,
|
||
"interpretation": "Artifact/finite/seed checks only; activity is descriptive."}
|
||
components.append(attempt(checks, "component:" + motif + ":" + policy, component_check))
|
||
|
||
unit_results = []
|
||
for precision in cfg["author_precisions"]:
|
||
for fixture in UNIT_NAMES:
|
||
def unit_check(precision=precision, fixture=fixture):
|
||
stem = fixture
|
||
record = read_json(EXP / "regression" / ("unit-" + stem + "-" + precision + ".json"))
|
||
require(record.get("fixture") == fixture and record.get("precision") == precision,
|
||
"Unit identity mismatch")
|
||
unit_cfg = dict(cfg, duration_ms=20.0)
|
||
seeded = fixture in ("refractory_boundary", "above_threshold")
|
||
directory = EXP / "oracle" / ("unit-" + stem + "-" + precision)
|
||
nodes = np.array([-2, -1]) if fixture == "delay_18" else np.array([-1])
|
||
seed = -2 if fixture == "delay_18" else (-1 if seeded else None)
|
||
actual, _ = load_trace(directory / "brian-output", nodes, 200, unit_cfg, seed,
|
||
natural_events=fixture == "nonzero_g_reset")
|
||
independent, _ = load_trace(directory / "independent-output", nodes, 200, unit_cfg, seed,
|
||
natural_events=fixture == "nonzero_g_reset")
|
||
raw = compare_raw(actual, independent, float(cfg["comparison"][precision + "_state_max_abs_tolerance_mv"]))
|
||
stored = read_json(directory / "comparison.json")
|
||
require(comparison_record_matches(raw, stored) and
|
||
comparison_record_matches(raw, record["comparison"]),
|
||
"Unit comparison differs from raw trajectories")
|
||
flags = record.get("checks")
|
||
require(isinstance(flags, dict) and bool(flags), "Empty unit checks cannot pass")
|
||
return {"pass": raw["pass_oracle"] and all(value is True for value in flags.values()),
|
||
"checks": flags, "raw_comparison": raw}
|
||
unit_results.append(attempt(checks, "unit:" + fixture + ":" + precision, unit_check))
|
||
|
||
author_results = []
|
||
precision_cross = []
|
||
for motif in cfg["motifs"]:
|
||
by_precision = {}
|
||
for precision in cfg["author_precisions"]:
|
||
def author_check(motif=motif, precision=precision):
|
||
nodes = motif_nodes(cfg, motif)
|
||
directory = EXP / "oracle" / (motif + "-" + precision)
|
||
seed = None if motif == "no_input" else cfg["seed_node"]
|
||
actual, per_node = load_trace(directory / "brian-output", nodes, steps, cfg, seed)
|
||
independent, _ = load_trace(directory / "independent-output", nodes, steps, cfg, seed)
|
||
by_precision[precision] = actual
|
||
outcomes.append({"motif": motif, "policy": "author_complete", "precision": precision,
|
||
"neurons": per_node, "activity_is_not_a_validation_gate": True})
|
||
raw = compare_raw(actual, independent, float(cfg["comparison"][precision + "_state_max_abs_tolerance_mv"]))
|
||
stored = read_json(directory / "comparison.json")
|
||
require(comparison_record_matches(raw, stored), "Author comparison differs from raw trajectories")
|
||
repeated, _ = load_trace(EXP / "oracle" / (motif + "-" + precision + "-repeat") /
|
||
"brian-output", nodes, steps, cfg, seed)
|
||
repeat_flags = read_json(EXP / "regression" / (motif + "-" + precision + "-repeat.json"))
|
||
require(set(repeat_flags) == set(actual) - {"nodes"}, "Incomplete repeat comparison fields")
|
||
repeat_raw = {key: bool(np.array_equal(actual[key], repeated[key])) for key in repeat_flags}
|
||
require(repeat_raw == repeat_flags, "Repeat flags disagree with raw arrays")
|
||
table = pd.read_csv(EXP / "audit/all-motif-results.csv", float_precision="round_trip")
|
||
check_summary_rows(table, motif, "author_complete", precision, per_node)
|
||
return {"pass": raw["pass_oracle"] and all(repeat_raw.values()),
|
||
"raw_comparison": raw, "repeat_exact": repeat_raw}
|
||
author_results.append(attempt(checks, "author:" + motif + ":" + precision, author_check))
|
||
def cross_check(motif=motif):
|
||
raw = compare_raw(by_precision["float32"], by_precision["float64"],
|
||
float(cfg["comparison"]["float32_state_max_abs_tolerance_mv"]))
|
||
stored = read_json(EXP / "regression" / (motif + "-precision-cross-comparison.json"))
|
||
require(comparison_record_matches(raw, stored), "Precision cross comparison differs from raw trajectories")
|
||
return {"pass": True, "comparison": raw,
|
||
"interpretation": "Reporting consistency only; cross-precision divergence is allowed and retained."}
|
||
precision_cross.append(attempt(checks, "precision_cross_record:" + motif, cross_check))
|
||
|
||
retained_errors = []
|
||
for path in sorted(EXP.rglob("error.json")):
|
||
if EXCLUDED_PARTS.intersection(path.relative_to(EXP).parts):
|
||
continue
|
||
try:
|
||
error = read_json(path)
|
||
except Exception as exception:
|
||
error = exception_record(exception)
|
||
retained_errors.append({"path": path.relative_to(EXP).as_posix(), "error": error})
|
||
checks.append({"name": "no_recorded_oracle_errors", "pass": not retained_errors,
|
||
"errors": retained_errors})
|
||
final_prereg = attempt(checks, "preregistration_at_seal", lambda: {"pass": True, "record": check_prereg()})
|
||
save(EXP / "regression/preregistration-after.json", {
|
||
"initial": prereg, "at_seal": final_prereg, "observed_source_hashes": source_hashes()})
|
||
passed = bool(checks) and all(item["pass"] for item in checks)
|
||
summary = {"phase": cfg.get("phase", "4AD"),
|
||
"status": "COMPLETE-ORACLE-VALIDATED-LAB-ONLY" if passed else "INCOMPLETE-OR-FAILED-LAB-VALIDATION",
|
||
"laboratory_validation_pass": passed, "checks": checks,
|
||
"component_checks": components, "unit_checks": unit_results,
|
||
"frozen_five_gpu_check": frozen_five, "author_poi_interface_check": interface,
|
||
"author_oracle_checks": author_results, "precision_cross_checks": precision_cross,
|
||
"motif_outcomes": outcomes, "run_complete_record": run_complete,
|
||
"whole_brain_alternative_run": False, "conditioning_run": False,
|
||
"learning_achieved": False, "candidate_generated": False, "selected_variant": None,
|
||
"goal_remains_unachieved": True,
|
||
"limits": ["No whole-brain or learning experiment in this protocol.",
|
||
"No activity-based variant selection; silence is not a success gate.",
|
||
"Isolated motifs omit external network input and graded APL.",
|
||
"Author equations on MaleCNS motifs do not reproduce the original paper's full brain or sensory interface.",
|
||
"Linux host and Python patch differences prevent a binary-identical author-environment claim."]}
|
||
save(EXP / "audit/final-summary.json", summary)
|
||
failures = [item for item in checks if not item["pass"]]
|
||
lines = ["# Phase 4AD 作者动力学语义实验室", "", "状态:`" + summary["status"] + "`。", "",
|
||
"本轮仅有预声明的小回路与算子实验;没有整脑替代动力学运行、conditioning、学习成功或新学习候选。",
|
||
"检查以原始事件、状态轨迹和预注册误差界限重算。缺失、失败、非有限值或初始事件丢失均不能通过;放电减少或静默本身不构成成功。", "",
|
||
f"核查通过 {sum(item['pass'] for item in checks)}/{len(checks)} 项;失败或不完整 {len(failures)} 项。",
|
||
"冻结历史完整性:" + ("通过。" if integrity["pass"] else "失败或未完成,详见保存的错误。"),
|
||
"源码与输入预注册一致性:" + ("通过。" if prereg["pass"] and final_prereg["pass"] else "失败或未完成;不得授予验证成功。"), "",
|
||
"| 回路 | 语义 | 精度 | 总spikes | late spikes |", "|---|---|---|---:|---:|"]
|
||
for row in outcomes:
|
||
lines.append("| {} | {} | {} | {} | {} |".format(row["motif"], row["policy"], row["precision"],
|
||
sum(item["spikes"] for item in row["neurons"]), sum(item["late_spikes"] for item in row["neurons"])))
|
||
if not outcomes:
|
||
lines.append("| 无完整可读取结果 | 未执行或缺失 | — | — | — |")
|
||
lines.extend(["", "作者Brian2与独立NumPy比较:", "",
|
||
"| 实验 | 结果 | 事件一致 | 最大V/g误差 mV | 首次事件分歧step |", "|---|---|---|---:|---:|"])
|
||
for item in author_results:
|
||
raw = item.get("raw_comparison", {})
|
||
lines.append("| {} | {} | {} | {} | {} |".format(item["name"], "通过" if item["pass"] else "失败/缺失",
|
||
raw.get("exact_events", "未知"), raw.get("max_abs_mv", "未知"),
|
||
raw.get("first_event_divergence_step", "无或未取得")))
|
||
lines.extend(["", "float32与float64交叉比较仅记录精度影响,允许保留分歧,不能用于掩盖各自与独立oracle的失败。"])
|
||
for item in precision_cross:
|
||
raw = item.get("comparison")
|
||
if raw:
|
||
lines.append(f"- {item['name']}:事件一致={raw['exact_events']},最大误差={raw['max_abs_mv']} mV,首次事件分歧step={raw['first_event_divergence_step']}。")
|
||
if failures:
|
||
lines.extend(["", "失败与未完成项:", ""])
|
||
for item in failures:
|
||
detail = item.get("error", {}).get("message") or "原始条件未全部满足;完整字段见 final-summary.json。"
|
||
lines.append("- `" + item["name"] + "`:" + str(detail).replace("\n", " "))
|
||
lines.extend(["", "所有失败轨迹和错误文件原样保留;本简报没有选择获胜变体。",
|
||
"小回路缺少外部整脑输入与graded APL,不能证明整脑因果必要性、生物真实性或信息保持。初始诊断seed也不是作者的感官Poisson接口。",
|
||
"环境为Linux宿主,作者记录为Windows;Python补丁版本与环境差异见environment记录,不能称为二进制相同或原论文整脑复现。",
|
||
"后续整脑嗅觉比较仍须核查固定输入、实际送达事件、持续活动和信息保持;可用学习仍需至少5个训练seed、独立评估、MBON/downstream的A对中性B特异性及acquisition/reversal/retention/delayed-reward对照。",
|
||
"封存排除 .venv 与 __pycache__,保留环境安装报告;manifest列出payload哈希,checksums另含manifest,不存在自哈希循环。", ""])
|
||
with (EXP / "REPORT.md").open("x", encoding="utf-8") as stream:
|
||
stream.write("\n".join(lines))
|
||
seal(MODEL)
|
||
seal(EXP)
|
||
print(json.dumps({"status": summary["status"], "laboratory_validation_pass": passed,
|
||
"failed_checks": len(failures), "learning_achieved": False,
|
||
"whole_brain_alternative_run": False, "sealed": [str(MODEL), str(EXP)]},
|
||
ensure_ascii=False), flush=True)
|
||
return 0 if passed else 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|