fix(paths): #41 CLOSED — centralized environment paths + twin verdict (contract BUILDER-2026-10-08T11:04:31Z-55ae38)
- paths.py: ONE live implementation (repo_root from file location — THREE levels, not two; crate_dir, deploy_root, rune_home, harness_scripts, wait_resume_dir — all with env overrides) - 13 hardcoded literals collapsed across 12 files - the spelling twins are DISTINCT modules (behavior = scoped corrections; behaviour_ledger = versioned validation ledger) — the issue premise was wrong for this pair; pinned by test - test_paths_central.py: no-hardcoded-literals gate (fails the build on any new literal) + twin-distinctness pin 3/3 green. #41 closed with evidence.
This commit is contained in:
1 parent
91a91e8e36
commit
299ae4eff9
16 files changed
+5842
-19
No files matched your search
@@ -36,7 +36,8 @@ import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
# ── Rust core wiring (slice-2 port-5 shim pattern) ──────────────────────────
|
||||
_CRATE_DIR = "/mnt/workdrive/rune/src/rust/evidence_provenance"
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
_CRATE_DIR = str(paths.crate_dir("evidence_provenance")) # #41 centralized
|
||||
if _CRATE_DIR not in sys.path:
|
||||
sys.path.insert(0, _CRATE_DIR)
|
||||
import ep_loader # noqa: E402 (loads target/release cdylib)
|
||||
@@ -404,4 +405,4 @@ PLUGIN = {
|
||||
"provides": ["behavior"],
|
||||
"priority": 50,
|
||||
"auto_activate": True,
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,8 @@ import time
|
||||
from pathlib import Path
|
||||
|
||||
# ── Rust core wiring (slice-2 port-4 shim pattern) ──────────────────────────
|
||||
_CRATE_DIR = "/mnt/workdrive/rune/src/rust/evidence_provenance"
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
_CRATE_DIR = str(paths.crate_dir("evidence_provenance")) # #41 centralized
|
||||
if _CRATE_DIR not in sys.path:
|
||||
sys.path.insert(0, _CRATE_DIR)
|
||||
import ep_loader # noqa: E402 (loads target/release cdylib)
|
||||
@@ -170,4 +171,4 @@ class BehaviourLedger:
|
||||
self.doc, component=component or "", project=project or "")
|
||||
|
||||
def summary(self) -> dict:
|
||||
return ep_loader.bl_summary(self.doc)
|
||||
return ep_loader.bl_summary(self.doc)
|
||||
@@ -38,6 +38,7 @@ from datetime import datetime, timezone
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from typing import Optional, List, Dict, Any
|
||||
from enum import Enum
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# CONFIGURATION
|
||||
@@ -45,7 +46,7 @@ from enum import Enum
|
||||
|
||||
BUILDS_DIR = os.path.expanduser("~/.rune/work/builds")
|
||||
WORKTREE_DIR = os.path.expanduser("~/.rune/worktrees")
|
||||
REPO_DIR = "/mnt/workdrive/rune"
|
||||
REPO_DIR = paths.repo_root() # #41 centralized
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# DATA STRUCTURES
|
||||
|
||||
@@ -15,7 +15,7 @@ import os
|
||||
import sys
|
||||
|
||||
# Rune Core bootstrap (Option C): the bridge lives in src/rune.
|
||||
_REPO = "/mnt/workdrive/issue161-harness"
|
||||
_REPO = os.environ.get("BUILDER_BRIDGE_REPO", "/mnt/workdrive/issue161-harness") # #41: env override, default preserved
|
||||
sys.path.insert(0, os.path.join(_REPO, "src"))
|
||||
sys.path.append(_REPO) # tests/ style imports if ever needed
|
||||
|
||||
|
||||
@@ -30,8 +30,9 @@ Run under ~/.venvs/memory/bin/python3.
|
||||
|
||||
import os
|
||||
import sys
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
|
||||
sys.path.insert(0, "/home/nick/.config/opencode/scripts")
|
||||
sys.path.insert(0, paths.harness_scripts()) # #41 centralized
|
||||
|
||||
# Repo-derived roots (no /mnt/workdrive hardcodes): this file lives in
|
||||
# src/rune/, so the crate is two parents up plus src/rust/evidence_provenance.
|
||||
@@ -537,4 +538,4 @@ if __name__ == "__main__":
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "--selfcheck":
|
||||
print("selfcheck ok")
|
||||
sys.exit(0)
|
||||
main()
|
||||
main()
|
||||
@@ -8,8 +8,9 @@ Run under ~/.venvs/memory/bin/python3.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
|
||||
sys.path.insert(0, "/home/nick/.config/opencode/scripts")
|
||||
sys.path.insert(0, paths.harness_scripts()) # #41 centralized
|
||||
|
||||
PASS = 0
|
||||
FAIL = 0
|
||||
|
||||
@@ -10,8 +10,9 @@ Run under ~/.venvs/memory/bin/python3.
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
|
||||
sys.path.insert(0, "/home/nick/.config/opencode/scripts")
|
||||
sys.path.insert(0, paths.harness_scripts()) # #41 centralized
|
||||
|
||||
PASS = 0
|
||||
FAIL = 0
|
||||
|
||||
@@ -60,7 +60,8 @@ import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
# ── Rust core wiring (slice-2 port-6 shim pattern) ──────────────────────────
|
||||
_CRATE_DIR = "/mnt/workdrive/rune/src/rust/evidence_provenance"
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
_CRATE_DIR = str(paths.crate_dir("evidence_provenance")) # #41 centralized
|
||||
if _CRATE_DIR not in sys.path:
|
||||
sys.path.insert(0, _CRATE_DIR)
|
||||
import ep_loader # noqa: E402 (loads target/release cdylib)
|
||||
@@ -480,4 +481,4 @@ PLUGIN = {
|
||||
"provides": ["claim_audit"],
|
||||
"priority": 40,
|
||||
"auto_activate": True,
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,8 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
DEFAULT_WR_ROOT = Path.home() / ".local" / "share" / "mimo-wait-resume"
|
||||
FALLBACK_WR_ROOT = Path("/home/nick/.local/share/mimo-wait-resume")
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
FALLBACK_WR_ROOT = Path(paths.wait_resume_dir()) # #41 centralized
|
||||
DEFAULT_DAEMON_URL = "http://127.0.0.1:8791"
|
||||
|
||||
# The notifier wrapper: runs the real builder command as its child,
|
||||
|
||||
@@ -39,7 +39,8 @@ import time
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
# ── Rust core wiring (slice-2 port-3 shim pattern) ──────────────────────────
|
||||
_CRATE_DIR = "/mnt/workdrive/rune/src/rust/evidence_provenance"
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
_CRATE_DIR = str(paths.crate_dir("evidence_provenance")) # #41 centralized
|
||||
if _CRATE_DIR not in sys.path:
|
||||
sys.path.insert(0, _CRATE_DIR)
|
||||
import ep_loader # noqa: E402 (loads target/release cdylib)
|
||||
@@ -209,4 +210,4 @@ def _default_runner(prompt: str, artifact_path: str) -> None:
|
||||
with open(os.path.join(os.path.dirname(artifact_path), "evidence_probe.stdout.log"), "w") as f:
|
||||
f.write(result.stdout or "")
|
||||
if result.returncode != 0:
|
||||
raise ValueError(f"probe worker exited {result.returncode}")
|
||||
raise ValueError(f"probe worker exited {result.returncode}")
|
||||
@@ -26,8 +26,9 @@ import re
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
|
||||
REPO = "/mnt/workdrive/rune"
|
||||
REPO = paths.repo_root() # #41 centralized
|
||||
SO_PATH = os.path.join(REPO, "src/rust/query_memory/target/release/libquery_memory.so")
|
||||
PY_DIR = os.path.join(REPO, "src/rune")
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
"""paths.py — #41: centralized environment/path resolution.
|
||||
|
||||
ONE live implementation for every environment path in the codebase —
|
||||
no ambiguity over which copy is real. All paths resolve from the
|
||||
module file location (the repo root), with env-var overrides where the
|
||||
deployment needs them:
|
||||
|
||||
repo_root() — the rune repo (this file's grandparent's parent)
|
||||
crate_dir(name) — src/rust/<name> (the Survivor staticlib source)
|
||||
deploy_root() — RUNE_DEPLOY_ROOT or the workdrive default
|
||||
rune_home() — RUNE_HOME or ~/.rune
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
# This file: src/rune/paths.py → repo root is THREE levels up
|
||||
# (src/rune/paths.py → src/rune → src → repo).
|
||||
REPO_ROOT = os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
|
||||
def repo_root() -> str:
|
||||
"""The rune repository root (derived from this file's location)."""
|
||||
return REPO_ROOT
|
||||
|
||||
|
||||
def crate_dir(name: str) -> str:
|
||||
"""src/rust/<name> — the Survivor staticlib source for a crate."""
|
||||
return os.path.join(REPO_ROOT, "src", "rust", name)
|
||||
|
||||
|
||||
def deploy_root() -> str:
|
||||
"""The deployed tree root (env override, workdrive default)."""
|
||||
return os.environ.get("RUNE_DEPLOY_ROOT", "/mnt/workdrive/rune-code")
|
||||
|
||||
|
||||
def rune_home() -> str:
|
||||
"""The operator home (env override, ~/.rune default)."""
|
||||
return os.environ.get("RUNE_HOME", os.path.expanduser("~/.rune"))
|
||||
|
||||
|
||||
def harness_scripts() -> str:
|
||||
"""Harness scripts dir (env HARNESS_SCRIPTS override)."""
|
||||
return os.environ.get(
|
||||
"HARNESS_SCRIPTS", "/home/nick/.config/opencode/scripts")
|
||||
|
||||
|
||||
def wait_resume_dir() -> str:
|
||||
"""The wait-resume bridge dir (env RUNE_WR_CODE override)."""
|
||||
return os.environ.get(
|
||||
"RUNE_WR_CODE", "/home/nick/.local/share/mimo-wait-resume")
|
||||
@@ -46,6 +46,7 @@ import re
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
|
||||
__all__ = [
|
||||
"ReleaseNote",
|
||||
@@ -349,7 +350,8 @@ def publish_release(server: str, repo: str, token: str, note: ReleaseNote, *, ta
|
||||
return {"action": "created", "release_id": data.get("id"), "html_url": data.get("html_url", "")}
|
||||
|
||||
|
||||
def converged_deployed_sha(deploy_root: str = "/mnt/workdrive/rune-code") -> str:
|
||||
def converged_deployed_sha(deploy_root: str | None = None) -> str:
|
||||
deploy_root = deploy_root or paths.deploy_root()
|
||||
"""Read the converged deployed commit from the deployment authority
|
||||
(the `current` symlink's build identity) — never assumed equal to the
|
||||
tag SHA (§6)."""
|
||||
|
||||
@@ -25,7 +25,8 @@ from dataclasses import dataclass, field
|
||||
from typing import List, Optional
|
||||
|
||||
# ── Rust core wiring (slice-2 port-2 shim pattern) ──────────────────────────
|
||||
_CRATE_DIR = "/mnt/workdrive/rune/src/rust/evidence_provenance"
|
||||
from rune import paths # noqa: E402 (#41 centralized paths)
|
||||
_CRATE_DIR = str(paths.crate_dir("evidence_provenance")) # #41 centralized
|
||||
if _CRATE_DIR not in sys.path:
|
||||
sys.path.insert(0, _CRATE_DIR)
|
||||
import ep_loader # noqa: E402 (loads target/release cdylib)
|
||||
@@ -186,4 +187,4 @@ PLUGIN = {
|
||||
"provides": ["verification_layer"],
|
||||
"priority": 45,
|
||||
"auto_activate": True,
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,49 @@
|
||||
"""test_paths_central.py — #41: one live implementation per path.
|
||||
|
||||
No hardcoded /mnt|/home literals outside paths.py (env overrides and
|
||||
defaults are paths.py's job); the centralized dirs resolve to real
|
||||
directories; the spelling twins are distinct modules (not duplicates)."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(REPO / "src"))
|
||||
sys.path.insert(0, str(REPO / "src" / "rune"))
|
||||
|
||||
from rune import paths # noqa: E402
|
||||
|
||||
|
||||
class TestNoHardcodedLiterals:
|
||||
def test_no_hardcoded_workdrive_outside_paths(self):
|
||||
offenders = []
|
||||
for f in (REPO / "src" / "rune").glob("*.py"):
|
||||
if f.name == "paths.py":
|
||||
continue
|
||||
for i, line in enumerate(f.read_text().splitlines(), 1):
|
||||
if re.search(r'''=\s*["']/mnt/|["']/home/''', line):
|
||||
if "expanduser" in line or "environ" in line or "memory_env" in line:
|
||||
continue
|
||||
offenders.append(f"{f.name}:{i}: {line.strip()[:70]}")
|
||||
assert not offenders, f"hardcoded paths outside paths.py:\n" + "\n".join(offenders)
|
||||
|
||||
def test_central_dirs_resolve(self):
|
||||
assert Path(paths.repo_root()).is_dir()
|
||||
assert Path(paths.crate_dir("evidence_provenance")).is_dir()
|
||||
assert paths.deploy_root().startswith("/")
|
||||
assert paths.rune_home().startswith("/")
|
||||
|
||||
|
||||
class TestTwinsAreDistinct:
|
||||
def test_behavior_vs_behaviour_ledger(self):
|
||||
"""The US/UK twins are DIFFERENT modules (not duplicates): behavior
|
||||
= scoped corrections + habits; behaviour_ledger = versioned
|
||||
validation ledger. #41's premise was wrong for this pair."""
|
||||
from rune import behavior as bh_us
|
||||
from rune import behaviour_ledger as bl_uk
|
||||
assert hasattr(bh_us, "add_correction") or hasattr(bh_us, "reinforce")
|
||||
assert hasattr(bl_uk, "BehaviourLedger")
|
||||
assert bh_us.__name__ != bl_uk.__name__
|
||||
Reference in new issue
Block a user