Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions gitgalaxy/tools/network_auditing/full_api_network_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@
from pathlib import Path
from typing import Any

try:
import yaml
except ImportError:
yaml = None

# ==============================================================================
# 1. ROUTER STRUCTURAL SIGNATURES (EXPANDED FRAMEWORK REGEX PATTERNS)
# ==============================================================================
Expand Down Expand Up @@ -168,12 +163,16 @@ def parse_official_swagger(swagger_path: Path) -> set:
try:
with open(swagger_path, encoding="utf-8") as f:
if swagger_path.suffix.lower() in [".yaml", ".yml"]:
if yaml is None:
# Imported here, not as a module-level `yaml = None` fallback, which
# type-checks differently with and without types-PyYAML installed (#3386).
try:
import yaml
except ImportError:
# Fix #165: Pipeline Assassin. Raise exception instead of sys.exit()
raise RuntimeError(
f"PyYAML is required to parse .yaml Swagger files ({swagger_path.name}). "
"Install with `pip install gitgalaxy[yaml]`."
)
) from None
swagger_data = yaml.safe_load(f)
else:
swagger_data = json.load(f)
Expand Down
45 changes: 45 additions & 0 deletions tests/_crucible_pin.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,48 @@
"""

PINNED_TAG = "v1.4.0"

# Escape hatch for deliberate off-pin runs (e.g. preparing a pin bump against an
# untagged crucible commit). Everything else treats a mismatch as an error.
ALLOW_UNPINNED_ENV = "LANGUAGE_CRUCIBLE_ALLOW_UNPINNED"


def pin_mismatch(crucible_path):
"""Returns None when the language-crucible checkout at `crucible_path` is on
PINNED_TAG, else an actionable message ending in the exact commands that fix
it (#3386). A stale checkout produces thousands of phantom golden-master
diffs with no error of its own (PR #2518), so callers fail on this rather
than warn. Compares commits, not tag names, so any tag pointing at the pinned
commit passes. Returns None for a checkout that isn't a git repo (e.g. an
unpacked release archive) or when ALLOW_UNPINNED_ENV is set to 1.
"""
import os
import subprocess
from pathlib import Path

if os.environ.get(ALLOW_UNPINNED_ENV) == "1":
return None
path = Path(crucible_path)

def rev(ref):
result = subprocess.run(
["git", "-C", str(path), "rev-parse", "--verify", "--quiet", f"{ref}^{{commit}}"],
capture_output=True,
text=True,
)
return result.stdout.strip() if result.returncode == 0 else None

if not (path / ".git").exists():
return None
head, pinned = rev("HEAD"), rev(PINNED_TAG)
if head and head == pinned:
return None
described = subprocess.run(
["git", "-C", str(path), "describe", "--tags", "--always"], capture_output=True, text=True
).stdout.strip()
return (
f"language-crucible at {path} is on {described or 'an unknown commit'}, but CI pins {PINNED_TAG} "
f"(tests/_crucible_pin.py). An off-pin corpus yields thousands of unrelated golden-master diffs.\n"
f"Fix: git -C {path} fetch --tags origin && git -C {path} checkout {PINNED_TAG}\n"
f"(Deliberately off-pin? Set {ALLOW_UNPINNED_ENV}=1.)"
)
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"WS-VARIABLES",
"WS-XREF-RID"
],
"total_paras": 0,
"total_paras": 13,
"dead_paras": [],
"loc_saved": 29
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"WS-INPUT-VARS",
"WS-MISC-VARS"
],
"total_paras": 0,
"total_paras": 9,
"dead_paras": [],
"loc_saved": 9
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"WS-RESP-QUEUE-STS",
"WS-VARIABLES"
],
"total_paras": 0,
"total_paras": 13,
"dead_paras": [],
"loc_saved": 15
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,12 @@
"WS-XREF-READ-FLG",
"WS-XREF-RID"
],
"total_paras": 42,
"total_paras": 43,
"dead_paras": [
"1200-EXIT",
"9500-EXIT",
"9990-EXIT"
],
"loc_saved": 86
"loc_saved": 76
},
"lineage": {
"program_id": "COPAUA0C",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,11 @@
"WS-TIMESTAMP-TM-SS",
"WS-TRANTYPE-MASTER-READ-FLAG"
],
"total_paras": 0,
"dead_paras": [],
"loc_saved": 173
"total_paras": 63,
"dead_paras": [
"0000-MAIN-EXIT"
],
"loc_saved": 183
},
"lineage": {
"program_id": "00220000",
Expand Down
54 changes: 54 additions & 0 deletions tests/test_crucible_pin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""#3386: an off-pin language-crucible checkout fails with the exact fix command."""

import subprocess
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent))
import _crucible_pin
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed

ALLOW_UNPINNED_ENV = _crucible_pin.ALLOW_UNPINNED_ENV


def _git(repo, *args):
subprocess.run(["git", "-C", str(repo), *args], check=True, capture_output=True)


def _repo(tmp_path):
repo = tmp_path / "language-crucible"
repo.mkdir()
_git(repo, "init", "-q")
for msg in ("old", "pinned"):
_git(repo, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty", "-m", msg)
_git(repo, "tag", "v0.0.1" if msg == "old" else _crucible_pin.PINNED_TAG)
return repo


def test_on_pin_passes(tmp_path, monkeypatch):
monkeypatch.delenv(ALLOW_UNPINNED_ENV, raising=False)
assert _crucible_pin.pin_mismatch(_repo(tmp_path)) is None


def test_off_pin_names_the_checkout_command(tmp_path, monkeypatch):
monkeypatch.delenv(ALLOW_UNPINNED_ENV, raising=False)
repo = _repo(tmp_path)
_git(repo, "checkout", "-q", "v0.0.1")
message = _crucible_pin.pin_mismatch(repo)
assert "v0.0.1" in message
assert f"git -C {repo} fetch --tags origin && git -C {repo} checkout {_crucible_pin.PINNED_TAG}" in message


def test_missing_pinned_tag_is_a_mismatch(tmp_path, monkeypatch):
monkeypatch.delenv(ALLOW_UNPINNED_ENV, raising=False)
repo = _repo(tmp_path)
monkeypatch.setattr(_crucible_pin, "PINNED_TAG", "v99.0.0")
assert "v99.0.0" in _crucible_pin.pin_mismatch(repo)


def test_escape_hatch_and_non_git_corpus_pass(tmp_path, monkeypatch):
repo = _repo(tmp_path)
_git(repo, "checkout", "-q", "v0.0.1")
monkeypatch.setenv(ALLOW_UNPINNED_ENV, "1")
assert _crucible_pin.pin_mismatch(repo) is None
monkeypatch.delenv(ALLOW_UNPINNED_ENV)
assert _crucible_pin.pin_mismatch(tmp_path / "unpacked-archive") is None
8 changes: 7 additions & 1 deletion tests/test_golden_crucible.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

sys.path.insert(0, str(Path(__file__).parent))
import golden_diff
from _crucible_pin import PINNED_TAG
from _crucible_pin import PINNED_TAG, pin_mismatch

pytestmark = pytest.mark.golden_crucible

Expand All @@ -52,6 +52,12 @@ def _zero_dependency_mode() -> bool:
),
)
def test_golden_crucible_matches_baseline(tmp_path):
# Fail fast, before a multi-minute scan, on the corpus drift that otherwise shows up
# as thousands of phantom diffs (#3386).
mismatch = pin_mismatch(CRUCIBLE_DATA_PATH.parent)
if mismatch:
pytest.fail(mismatch, pytrace=False)

zero_dep = _zero_dependency_mode()
golden_master_path = REPO_ROOT / (
"tests/golden_master_zero_dep_audit.json" if zero_dep else "tests/golden_master_audit.json"
Expand Down
39 changes: 17 additions & 22 deletions tests/tools/crucible_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
incident writeups -- both cost real hours on PR #2518, 2026-08-30, chasing phantom diffs that
had nothing to do with the actual code change under test):

1. Corpus pin drift: warns if the local language-crucible sibling isn't on the tag
`tests/_crucible_pin.py` names.
1. Corpus pin drift: FAILS (with the exact checkout command) if the local
language-crucible sibling isn't on the tag `tests/_crucible_pin.py` names (#3386).
2. Unsafe corpus path: warns if the corpus's own absolute path contains an
IGNORED_DIRECTORIES name (e.g. "tmp") as ANY path component -- this silently zeroes
out documentation-coverage scoring for the ENTIRE corpus with no error message.
Expand Down Expand Up @@ -71,7 +71,7 @@
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))
from _crucible_pin import PINNED_TAG
from _crucible_pin import PINNED_TAG, pin_mismatch

REPO_ROOT = Path(__file__).parent.parent.parent
VENV_BASE = REPO_ROOT / ".crucible_venvs"
Expand Down Expand Up @@ -148,24 +148,18 @@ def _find_ci_python() -> str:
return sys.executable


def _check_corpus_pin() -> None:
"""Warns (never blocks -- someone may have a deliberate reason to point at a different
ref) if the local corpus isn't on the pinned tag. A stale or wrong-branch sibling
checkout produces thousands of unrelated diff lines with no error message of its own,
easily mistaken for a real code regression (confirmed real, PR #2518, 2026-08-30: a
corpus 20 commits past an old, different tag produced ~4000 phantom diffs)."""
result = subprocess.run(
["git", "-C", str(CRUCIBLE_PATH), "describe", "--tags", "--exact-match"],
capture_output=True,
text=True,
)
current = result.stdout.strip() if result.returncode == 0 else None
if current != PINNED_TAG:
print(
f"⚠️ language-crucible at {CRUCIBLE_PATH} is on {current or '(not exactly on any tag)'}, not the pinned {PINNED_TAG}."
)
print(" This alone can produce thousands of unrelated diff lines against the committed fixtures. Fix:")
print(f" git -C {CRUCIBLE_PATH} fetch --tags && git -C {CRUCIBLE_PATH} checkout {PINNED_TAG}")
def _check_corpus_pin() -> bool:
"""Fails (returns False) if the local corpus isn't on the pinned tag. A stale or
wrong-branch sibling checkout produces thousands of unrelated diff lines with no error
message of its own, easily mistaken for a real code regression (confirmed real, PR #2518,
2026-08-30: a corpus 20 commits past an old, different tag produced ~4000 phantom diffs).
Used to only warn, which every agent in the #3249 round read past (#3386); set
LANGUAGE_CRUCIBLE_ALLOW_UNPINNED=1 for a deliberate off-pin run."""
mismatch = pin_mismatch(CRUCIBLE_PATH)
if mismatch:
print(f"❌ {mismatch}")
return False
return True


def _check_unsafe_corpus_path(py: Path) -> None:
Expand Down Expand Up @@ -324,7 +318,8 @@ def main() -> int:
print(" or set LANGUAGE_CRUCIBLE_PATH, then re-run.")
return 1

_check_corpus_pin()
if not _check_corpus_pin():
return 1

mode_keys = ["full", "zero"] if args.mode == "both" else [args.mode]

Expand Down
8 changes: 7 additions & 1 deletion tests/tools/update_golden_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

sys.path.insert(0, str(Path(__file__).parent.parent))
import golden_diff
from _crucible_pin import PINNED_TAG
from _crucible_pin import PINNED_TAG, pin_mismatch

from gitgalaxy.galaxyscope import HAS_PYYAML, HAS_TIKTOKEN
from gitgalaxy.security.security_auditor import ML_AVAILABLE
Expand Down Expand Up @@ -64,6 +64,12 @@ def main():
print(" or set LANGUAGE_CRUCIBLE_PATH, then re-run.")
sys.exit(1)

# Blessing against an off-pin corpus bakes its drift into the committed masters (#3386).
mismatch = pin_mismatch(CRUCIBLE_DATA_PATH.parent)
if mismatch:
print(f"❌ {mismatch}")
sys.exit(1)

zero_dep = zero_dependency_mode()
mode_name = "zero-dependency" if zero_dep else "full-precision"
golden_master_path = REPO_ROOT / (
Expand Down
Loading