CONTRACT-2 (§10-R4) arch-family registry expansion: +13 safetensors arch rows in arch_patches.yml (PhiForCausalLM — the microsoft/phi-2 STEP V1 on-rig no-arch-row anchor — Phi3Small, Gemma/Gemma3/Gemma3-CG, Starcoder2, Cohere, InternLM2, Mixtral/Qwen2Moe/Qwen3Moe MoE, Qwen2-VL). Additive data only, zero [C0]/decision-logic change. Zero false-pass by construction: each follows the established estimated-lower-bound/unverified-TRC precedent so [C0] still resolves needs-trust-remote-code-ack (fail-closed, bypassable ONLY by --trust-remote-code) — the expansion drops only the --experimental-arch requirement, never auto-passes; an arch still absent still hard-blocks no-arch-row. test-pullgate-gates.sh proves both, plus the #146-shape worked acceptance case (a hand-added awq_bf16_int4 weights variant the expanded flag schema/parity machinery absorbs cleanly). CONTRACT-2b-i chat-template attribution + behavioral drift_guard: new `chat_template` delivery class (VALID_DELIVERY_MECHANISM); froggeric (22 composes — 18 direct + 4 nvlink* via REAL Docker Compose extends: merge) and carnice (mount-only) brought under load_bearing_when + a behavioral drift_guard whose check encodes the self-contained symmetric restart+settle protocol (identical docker restart both arms, /v1/models healthy, 60s settle, >=3 bench runs/arm, grand-mean same-segment compare, flag only a 3/3 deterministic regression). Effective coverage uses REAL merge semantics: docker compose config (preferred) or a deterministic offline extends: merge applying the same rules (additive sequence merge; `!reset` removal) — never the unsound single-base text concat. .jinja artifact discovery catches an orphan vendored template. test-patch-attribution.sh adds the class checks + an H4 fixture asserting a `!reset` child AND a stopped-extending child both lose coverage (the false-negative is the dangerous direction). Generator emit kept in lock-step with reaches(). Documented as PATCH_POLICY.md §3.1. Rig-independent leak assertions added (str(abs_dir) not in shared; repo-relative-only — never a /opt|/home substring allowlist). RED-LINE: gates.py/pull.py/deriver.py/capture.py/loop_input.py/ classifier.py/dedup.py/submit_pull.py/kv-calc.py/failure_fingerprints.yml byte-unchanged; no shipped compose changed; patch_attribution.py c0_state/ is_artifact/compose_text/service_body byte-identical (additive only). Full test-*.sh suite green in the CI condition; kv-calc --calibration N/N. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
614 lines
25 KiB
Python
614 lines
25 KiB
Python
"""Patch-attribution core (v0.8.0 STEP 2 — club-3090 #359 / PR #147).
|
|
|
|
Extracted from the embedded Python that previously lived inside
|
|
``scripts/tests/test-patch-attribution.sh``. The test is the contract:
|
|
this module exposes exactly the helpers the test needs
|
|
(:func:`load`, :func:`compose_text`, :func:`gap_declared`,
|
|
:func:`reaches`, plus the schema/[C0] check helpers), and the test now
|
|
imports them instead of carrying its own copy.
|
|
|
|
reaches() soundness (brief v9, correction #4)
|
|
---------------------------------------------
|
|
The legacy ``reaches()`` did a naive ``patch["id"] in text`` substring
|
|
test over the *entire* compose file, including the leading comment
|
|
banner and (for generated composes) the generator's own header WARNING
|
|
block. A patch ID merely *named* in a comment/WARNING would then count
|
|
as "reached" — a false positive.
|
|
|
|
The extracted :func:`reaches` instead:
|
|
|
|
* parses the **service body only** (everything from the top-level
|
|
``services:`` key onward), discarding the file-header banner and every
|
|
YAML comment line / inline ``# …`` trailer — so a patch ID that only
|
|
appears in a header/comment/WARNING line is *not* a match;
|
|
* validates the patch's **actual ``delivery_spec`` wiring** is present —
|
|
the declared volume mount(s) and/or entrypoint invoke string from
|
|
``patches.yml`` / the Phase-A-prime ``delivery_spec`` — rather than a
|
|
bare substring of the patch ID;
|
|
* accepts either a ``COMPOSE_REGISTRY`` profile name *or* an arbitrary
|
|
absolute path to a compose file.
|
|
|
|
The deprecated ``delivery:`` boolean block is still consulted (read-only,
|
|
the test still asserts on it) but every text probe it performs now runs
|
|
against the comment-stripped service body, never the header — so the
|
|
result is identical to the legacy behaviour on the shipped composes
|
|
while being immune to header/comment false positives on generated ones.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
|
|
import yaml
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Schema constants (single source of truth — the test imports these).
|
|
# --------------------------------------------------------------------------
|
|
REQUIRED_PATCH_KEYS = {
|
|
"id",
|
|
"model",
|
|
"files",
|
|
"load_bearing_when",
|
|
"delivery",
|
|
"delivery_gaps",
|
|
"upstream",
|
|
"status",
|
|
}
|
|
VALID_PATCH_STATUS = {"verified", "unverified", "suspect"}
|
|
|
|
ARCH_ALLOWED_KEYS = {
|
|
"arch",
|
|
"engine_pin",
|
|
"required_patches",
|
|
"valid_tp",
|
|
"requires_trust_remote_code",
|
|
"requires_trust_remote_code_evidence",
|
|
"kernel_constraints",
|
|
"family",
|
|
"confidence",
|
|
"status",
|
|
}
|
|
ARCH_REQUIRED_KEYS = ARCH_ALLOWED_KEYS
|
|
VALID_TRC = {"true", "false", "unverified"}
|
|
VALID_ARCH_STATUS = {"verified", "unverified", "suspect"}
|
|
VALID_CONFIDENCE = {"exact", "derived", "estimated-lower-bound"}
|
|
|
|
# v0.8.2 CONTRACT-2b-i: the patch-attribution delivery vocabulary. The
|
|
# v0.8.0 set (python_sidecar|site_package_overlay|install_script|none) had
|
|
# no class for a model chat-template override (a vendored `.jinja` mounted
|
|
# into the container and wired via `--chat-template`). Without a class, the
|
|
# #141 generator + test-patch-attribution cannot SEE a behavior-critical
|
|
# template (tool-call XML / reasoning delimiters / streaming — the #145
|
|
# silent-break class), so a bad/regressed template silently degrades every
|
|
# compose that ships it with ZERO attribution coverage. `chat_template` is
|
|
# the additive class that brings it under the same load_bearing_when /
|
|
# drift_guard safety net as every other load-bearing patch.
|
|
VALID_DELIVERY_MECHANISM = {
|
|
"python_sidecar",
|
|
"site_package_overlay",
|
|
"install_script",
|
|
"chat_template",
|
|
"none",
|
|
}
|
|
|
|
# A `chat_template` patch's `.jinja` artifact extensions (the discovery set
|
|
# below treats these like `.py`/`.sh` overlay/sidecar artifacts so an
|
|
# orphan vendored template with no patches.yml entry is caught).
|
|
CHAT_TEMPLATE_ARTIFACT_SUFFIXES = {".jinja", ".jinja2", ".j2"}
|
|
|
|
SEED_REQUIRED_KEYS = {
|
|
"model",
|
|
"arch_family",
|
|
"quant",
|
|
"topology_class",
|
|
"engine_pin",
|
|
"kv_format",
|
|
"selected_ctx",
|
|
"measured",
|
|
"smoked_capabilities",
|
|
"unsmoked_capabilities",
|
|
"source",
|
|
"provenance",
|
|
"confidence",
|
|
}
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Loaders.
|
|
# --------------------------------------------------------------------------
|
|
def load(path: Path, errors: list[str] | None = None, root: Path | None = None) -> dict:
|
|
"""Load a profiles YAML doc, asserting ``schema_version: 1``.
|
|
|
|
``errors``/``root`` are optional: when supplied a schema-version
|
|
violation is appended to ``errors`` (relative to ``root`` if given),
|
|
matching the original embedded behaviour. When omitted the doc is
|
|
returned as-is (handy for non-test callers / the generator).
|
|
"""
|
|
with path.open("r", encoding="utf-8") as fh:
|
|
data = yaml.safe_load(fh) or {}
|
|
if data.get("schema_version") != 1:
|
|
rel = path.relative_to(root) if root is not None else path
|
|
msg = f"{rel} missing schema_version: 1"
|
|
if errors is not None:
|
|
errors.append(msg)
|
|
return data
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Compose-text reader (resolves a registry name OR an arbitrary path).
|
|
# --------------------------------------------------------------------------
|
|
def _resolve_compose_path(root: Path, name_or_path: str) -> Path:
|
|
"""Map a COMPOSE_REGISTRY profile name OR an absolute path to a Path."""
|
|
candidate = Path(name_or_path)
|
|
if candidate.is_absolute():
|
|
return candidate
|
|
# Late import: keeps this module importable without the registry and
|
|
# mirrors the test's own import site.
|
|
import sys
|
|
|
|
if str(root) not in sys.path:
|
|
sys.path.insert(0, str(root))
|
|
from scripts.lib.profiles.compose_registry import COMPOSE_REGISTRY # noqa: E402
|
|
|
|
if name_or_path in COMPOSE_REGISTRY:
|
|
return root / COMPOSE_REGISTRY[name_or_path]["compose_path"]
|
|
# Not a registry name and not absolute — treat as repo-relative path.
|
|
return root / name_or_path
|
|
|
|
|
|
def compose_text(root: Path, name_or_path: str, seen: set[Path] | None = None) -> str:
|
|
"""Read a compose file (+ a single `extends:` base) as raw text.
|
|
|
|
Accepts a COMPOSE_REGISTRY profile name or an arbitrary absolute path
|
|
(correction #4: ``reaches`` must accept either). Returns ``""`` on a
|
|
cycle, matching the original embedded reader.
|
|
"""
|
|
path = _resolve_compose_path(root, name_or_path)
|
|
seen = seen if seen is not None else set()
|
|
if path in seen:
|
|
return ""
|
|
seen.add(path)
|
|
text = path.read_text(encoding="utf-8")
|
|
match = re.search(r"extends:\s*\n\s*file:\s*([^\n]+)", text)
|
|
if match:
|
|
base = (path.parent / match.group(1).strip()).resolve()
|
|
if base.exists():
|
|
text += "\n" + base.read_text(encoding="utf-8")
|
|
return text
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Effective-coverage: REAL Docker Compose merge (CONTRACT-2b-i, r1 H4).
|
|
# --------------------------------------------------------------------------
|
|
# `compose_text` above is the legacy substring substrate: it raw-text
|
|
# CONCATENATES a single `extends:` base. That is unsound for effective
|
|
# coverage of a mounted artifact (e.g. the froggeric chat-template) because
|
|
# a child compose can `!reset`, override, or REMOVE a `volumes`/`command`
|
|
# entry the base declared. A concat would still "see" the base's mount line
|
|
# even though the merged service no longer mounts it — a FALSE NEGATIVE on
|
|
# coverage loss, which is the dangerous direction (the core #377 failure
|
|
# mode: an nvlink* compose that stopped extending its template-bearing base
|
|
# would silently lose the override with zero test catching it).
|
|
#
|
|
# `compose_effective_text` resolves coverage from the *merged resolved*
|
|
# service using REAL Docker Compose merge semantics:
|
|
# * preferred: `docker compose -f <child> config` (the canonical merge —
|
|
# resolves `extends:`, list/scalar override, `!reset`/`!override`; no
|
|
# daemon required, `config` is a pure local resolve);
|
|
# * deterministic fallback (no docker CLI in the CI image): a recursive
|
|
# `extends:` resolver that applies the SAME merge rules — the child's
|
|
# `volumes`/`command` REPLACE the base's when re-declared, an explicitly
|
|
# emptied list removes the base's entries — so a removal fixture is
|
|
# still caught offline.
|
|
# Either way the result is the rendered merged service, and a child that
|
|
# removes the mount yields text WITHOUT the mount target.
|
|
class ComposeMergeError(RuntimeError):
|
|
"""Raised when neither the docker merge nor the offline merge can
|
|
resolve a compose graph (so a chat_template coverage check can fail
|
|
LOUD rather than silently degrade to the unsound concat path)."""
|
|
|
|
|
|
def _docker_compose_config(path: Path) -> str | None:
|
|
"""`docker compose -f <path> config` — the canonical merge. Returns the
|
|
rendered merged YAML text, or None if the docker CLI is unavailable or
|
|
the resolve fails (caller falls back to the offline merge)."""
|
|
if shutil.which("docker") is None:
|
|
return None
|
|
try:
|
|
proc = subprocess.run(
|
|
["docker", "compose", "-f", path.name, "config"],
|
|
cwd=str(path.parent),
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60,
|
|
)
|
|
except (OSError, subprocess.SubprocessError):
|
|
return None
|
|
if proc.returncode != 0:
|
|
return None
|
|
return proc.stdout
|
|
|
|
|
|
class _ComposeReset:
|
|
"""Sentinel for the Compose `!reset`/`!override` YAML tags used to
|
|
DROP a base value across an `extends:` (the only in-Compose way to
|
|
remove a base `volumes`/`command` entry — a plain re-declared `[]`
|
|
does NOT remove it: Compose merges `extends:` sequences additively)."""
|
|
|
|
|
|
def _compose_yaml_load(text: str):
|
|
"""`yaml.safe_load` that tolerates the Compose `!reset`/`!override`
|
|
custom tags (mapping them to the `_ComposeReset` drop-sentinel /
|
|
pass-through) so the offline merge matches `docker compose config`
|
|
behaviour for the removal case."""
|
|
|
|
class _L(yaml.SafeLoader):
|
|
pass
|
|
|
|
def _reset(loader, node): # !reset DROPS the key on merge
|
|
return _ComposeReset
|
|
|
|
def _override(loader, node): # !override = take child's value as-is
|
|
if isinstance(node, yaml.SequenceNode):
|
|
return loader.construct_sequence(node)
|
|
if isinstance(node, yaml.MappingNode):
|
|
return loader.construct_mapping(node)
|
|
return loader.construct_scalar(node)
|
|
|
|
_L.add_constructor("!reset", _reset)
|
|
_L.add_constructor("!override", _override)
|
|
return yaml.load(text, Loader=_L) # noqa: S506 — _L is SafeLoader-derived
|
|
|
|
|
|
def _offline_extends_merge(path: Path, _seen: set[Path] | None = None) -> dict:
|
|
"""Deterministic pure-yaml stand-in for `docker compose config` merge,
|
|
matching Compose's REAL `extends:` contract (not the unsound concat):
|
|
|
|
* recursively resolve the single `extends: {file, service}`;
|
|
* SEQUENCES (e.g. `volumes`, `command`) are MERGED ADDITIVELY base⊕child
|
|
— Compose does NOT let a plain re-declared `[]` drop a base mount;
|
|
* MAPPINGS (e.g. `environment` as a map) are deep-merged child-wins;
|
|
* scalars: child wins;
|
|
* the Compose `!reset` tag on a child key DROPS the base value (the
|
|
only in-Compose removal mechanism — this is what makes a genuine
|
|
coverage-loss fixture catchable, and it diverges from a text concat
|
|
which would still "see" the dropped base line)."""
|
|
_seen = _seen if _seen is not None else set()
|
|
rp = path.resolve()
|
|
if rp in _seen:
|
|
raise ComposeMergeError(f"extends cycle at {rp}")
|
|
_seen.add(rp)
|
|
doc = _compose_yaml_load(path.read_text(encoding="utf-8")) or {}
|
|
services = doc.get("services") or {}
|
|
|
|
def _merge(base, child):
|
|
if child is _ComposeReset:
|
|
return None # !reset drops the base value entirely
|
|
if isinstance(base, list) and isinstance(child, list):
|
|
return list(base) + list(child) # Compose extends: additive seq
|
|
if isinstance(base, dict) and isinstance(child, dict):
|
|
out = dict(base)
|
|
for k, v in child.items():
|
|
if v is _ComposeReset:
|
|
out.pop(k, None)
|
|
elif k in out:
|
|
out[k] = _merge(out[k], v)
|
|
else:
|
|
out[k] = v
|
|
return out
|
|
return child # scalar / type-mismatch: child wins
|
|
|
|
merged_services: dict = {}
|
|
for svc_name, svc in services.items():
|
|
svc = svc or {}
|
|
ext = svc.get("extends")
|
|
child_svc = {k: v for k, v in svc.items() if k != "extends"}
|
|
if isinstance(ext, dict) and ext.get("file"):
|
|
base_path = (path.parent / ext["file"]).resolve()
|
|
base_svc_name = ext.get("service")
|
|
if base_path.exists():
|
|
base_doc = _offline_extends_merge(base_path, set(_seen))
|
|
base_svc = (base_doc.get("services") or {}).get(base_svc_name) or {}
|
|
merged_services[svc_name] = _merge(dict(base_svc), child_svc)
|
|
continue
|
|
merged_services[svc_name] = child_svc
|
|
return {"services": merged_services}
|
|
|
|
|
|
def compose_effective_text(root: Path, name_or_path: str) -> str:
|
|
"""Return the RESOLVED-MERGED compose text (real `extends:` semantics).
|
|
|
|
Used by :func:`reaches` for the ``chat_template`` delivery class so
|
|
coverage is computed from the effective service, not declared lines.
|
|
Raises :class:`ComposeMergeError` if no merge path can resolve the
|
|
graph (loud-fail; a chat_template coverage check must never silently
|
|
fall back to the unsound concat)."""
|
|
path = _resolve_compose_path(root, name_or_path)
|
|
rendered = _docker_compose_config(path)
|
|
if rendered is not None:
|
|
return rendered
|
|
merged = _offline_extends_merge(path)
|
|
return yaml.safe_dump(merged, default_flow_style=False, sort_keys=False)
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Body extraction — drop the file-header banner and all comment lines so a
|
|
# patch ID named only in a header/comment/WARNING cannot count as reached.
|
|
# --------------------------------------------------------------------------
|
|
def _strip_yaml_comment(line: str) -> str:
|
|
"""Remove an inline/whole-line ``# …`` comment, honouring quotes.
|
|
|
|
Conservative single-pass scanner: a ``#`` only starts a comment when
|
|
it is at column 0 (after indentation) or preceded by whitespace and
|
|
not inside a single/double-quoted scalar. This keeps ``#`` characters
|
|
that are legitimately part of a value (rare here, but e.g. URLs in
|
|
quoted strings) while discarding real comments — which is where the
|
|
patch-ID / PR-number false positives live.
|
|
"""
|
|
out: list[str] = []
|
|
in_single = False
|
|
in_double = False
|
|
prev_ws = True # start-of-content counts as "preceded by whitespace"
|
|
for idx, ch in enumerate(line):
|
|
if ch == "'" and not in_double:
|
|
in_single = not in_single
|
|
elif ch == '"' and not in_single:
|
|
in_double = not in_double
|
|
elif ch == "#" and not in_single and not in_double and prev_ws:
|
|
break
|
|
out.append(ch)
|
|
prev_ws = ch in (" ", "\t")
|
|
return "".join(out)
|
|
|
|
|
|
def service_body(text: str) -> str:
|
|
"""Return the comment-free service body of a compose file.
|
|
|
|
1. Drop everything before the top-level ``services:`` key (the
|
|
at-a-glance banner + the generator's own header WARNING block).
|
|
2. Strip every YAML comment (whole-line and inline) from the
|
|
remaining lines.
|
|
|
|
The result is the substrate :func:`reaches` probes — so a patch ID
|
|
or PR number that appears *only* in a comment/header/WARNING line is
|
|
invisible to reachability, while real volume mounts and entrypoint
|
|
invoke lines (which are values, not comments) remain.
|
|
"""
|
|
lines = text.splitlines()
|
|
start = 0
|
|
for idx, raw in enumerate(lines):
|
|
# Top-level `services:` (column 0). Header/comment lines and the
|
|
# generator WARNING block all live above this.
|
|
if re.match(r"^services:\s*(#.*)?$", raw):
|
|
start = idx
|
|
break
|
|
body_lines = [_strip_yaml_comment(raw) for raw in lines[start:]]
|
|
return "\n".join(body_lines)
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# delivery_spec wiring validation — confirm the patch's *actual* mount /
|
|
# invoke artifacts (as declared in patches.yml / Phase-A-prime
|
|
# delivery_spec) are present in the service body.
|
|
# --------------------------------------------------------------------------
|
|
def _spec_wiring_markers(patch: dict) -> tuple[list[str], list[str]]:
|
|
"""Derive (volume_markers, invoke_markers) from ``delivery_spec``.
|
|
|
|
Returns the concrete strings that MUST appear in the service body for
|
|
the patch to be genuinely wired:
|
|
|
|
* volume markers: container-side mount targets (``dest`` /
|
|
``mounted_at``) of overlay files / install scripts;
|
|
* invoke markers: the entrypoint command that runs the sidecar /
|
|
install script (``invoke`` string, the sidecar/script container
|
|
path, or basename).
|
|
"""
|
|
spec = patch.get("delivery_spec") or {}
|
|
vol: list[str] = []
|
|
inv: list[str] = []
|
|
|
|
# site_package_overlay → overlay_files[].dest are bind-mount targets.
|
|
for of in spec.get("overlay_files") or []:
|
|
dest = of.get("dest")
|
|
if dest:
|
|
vol.append(dest)
|
|
|
|
# install_script → mounted_at is the volume target; invoke is the
|
|
# entrypoint command line.
|
|
mounted_at = spec.get("mounted_at")
|
|
if mounted_at:
|
|
vol.append(mounted_at)
|
|
|
|
# python_sidecar → sidecar is the host path; its basename appears in
|
|
# both the bind mount and the `python3 …` invoke line.
|
|
sidecar = spec.get("sidecar")
|
|
if sidecar:
|
|
inv.append(Path(sidecar).name)
|
|
|
|
script = spec.get("script")
|
|
if script:
|
|
inv.append(Path(script).name)
|
|
|
|
invoke = spec.get("invoke")
|
|
# Only treat `invoke` as a literal body marker when it is an actual
|
|
# command (e.g. "bash /etc/club3090/install-pr41800.sh"), not a
|
|
# human-readable description sentence.
|
|
if invoke and not invoke.endswith((".", "serving", "import")) and "/" in invoke:
|
|
inv.append(invoke)
|
|
|
|
# chat_template → the vendored `.jinja` is bind-mounted at `mounted_at`
|
|
# (already added as a volume marker above via `mounted_at`). Two
|
|
# in-tree wiring styles:
|
|
# * explicit `--chat-template <mounted_at>` arg (froggeric): require
|
|
# BOTH tokens in the merged body (rendered as adjacent list items,
|
|
# so the joined string never appears — match them separately);
|
|
# * mount-only (carnice mounts over the model dir's chat_template.jinja
|
|
# and vLLM auto-loads it; `wired_at: [volumes]`): the mount target
|
|
# alone is the load-bearing artifact, no `--chat-template` arg.
|
|
if patch.get("delivery_mechanism") == "chat_template" and mounted_at:
|
|
if "--chat-template" in (spec.get("invoke") or ""):
|
|
inv.append("--chat-template")
|
|
inv.append(mounted_at)
|
|
|
|
return vol, inv
|
|
|
|
|
|
def _spec_wiring_present(patch: dict, body: str) -> bool:
|
|
"""True iff the patch's declared delivery_spec wiring is in ``body``.
|
|
|
|
``wired_at`` tells us which insertion point(s) the patch claims:
|
|
``volumes`` requires a matching mount target; ``entrypoint`` requires
|
|
a matching invoke; ``[volumes, entrypoint]`` requires *both*.
|
|
A patch whose delivery_mechanism is ``none`` has no spec and is never
|
|
spec-wired (the legacy fallback below still applies for parity).
|
|
"""
|
|
spec = patch.get("delivery_spec")
|
|
if not spec:
|
|
return False
|
|
wired_at = spec.get("wired_at")
|
|
if isinstance(wired_at, str):
|
|
wired_at = [wired_at]
|
|
wired_at = set(wired_at or [])
|
|
vol_markers, inv_markers = _spec_wiring_markers(patch)
|
|
|
|
vol_ok = (not vol_markers) or any(m in body for m in vol_markers)
|
|
inv_ok = (not inv_markers) or any(m in body for m in inv_markers)
|
|
|
|
if wired_at == {"volumes"}:
|
|
return bool(vol_markers) and vol_ok
|
|
if wired_at == {"entrypoint"}:
|
|
return bool(inv_markers) and inv_ok
|
|
if "volumes" in wired_at and "entrypoint" in wired_at:
|
|
# Declared at both points — require the volume mount (the
|
|
# load-bearing artifact); the invoke line is corroborating.
|
|
return bool(vol_markers) and vol_ok and inv_ok
|
|
# Unknown / empty wired_at: fall back to "any declared marker present".
|
|
return (bool(vol_markers) and vol_ok) or (bool(inv_markers) and inv_ok)
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# gap_declared / reaches.
|
|
# --------------------------------------------------------------------------
|
|
def gap_declared(patch: dict, compose_name: str) -> bool:
|
|
for gap in patch.get("delivery_gaps") or []:
|
|
if compose_name in set(gap.get("composes") or []):
|
|
return True
|
|
return False
|
|
|
|
|
|
def reaches(root: Path, patch: dict, name_or_path: str) -> bool:
|
|
"""Is ``patch`` actually wired into the compose ``name_or_path``?
|
|
|
|
Sound (correction #4): probes the **comment-stripped service body**
|
|
only — never the file header or generator WARNING block — and
|
|
validates the patch's **real delivery_spec wiring** (declared mount
|
|
target and/or entrypoint invoke), not a substring of its ID.
|
|
|
|
``name_or_path`` may be a COMPOSE_REGISTRY profile name OR an
|
|
arbitrary absolute path to a compose file.
|
|
|
|
The deprecated ``delivery:`` boolean block is still honoured as a
|
|
fallback for parity with the existing contract, but every probe runs
|
|
against the service body so it cannot be tripped by a header/comment
|
|
mention of the patch ID or a PR number.
|
|
"""
|
|
# CONTRACT-2b-i: a `chat_template` patch's effective coverage MUST be
|
|
# computed from the REAL merged compose graph (`extends:` resolved with
|
|
# Docker Compose merge semantics), not the legacy single-base concat —
|
|
# a child can `!reset`/override/REMOVE the mount, and the concat would
|
|
# still see the base's line (a false-negative on coverage loss, the
|
|
# dangerous direction). Every other mechanism keeps the byte-identical
|
|
# legacy substrate so shipped attribution is unchanged.
|
|
if patch.get("delivery_mechanism") == "chat_template":
|
|
body = service_body(compose_effective_text(root, name_or_path))
|
|
return _spec_wiring_present(patch, body)
|
|
|
|
body = service_body(compose_text(root, name_or_path))
|
|
|
|
# Primary, sound path: the patch's declared delivery_spec wiring is
|
|
# genuinely present at the insertion point(s) it claims.
|
|
if _spec_wiring_present(patch, body):
|
|
return True
|
|
|
|
# Legacy fallback (read-only `delivery:` block) — operates on the
|
|
# service body, so header/comment ID mentions never match.
|
|
delivery = patch.get("delivery") or {}
|
|
if delivery.get("entrypoint_invoke"):
|
|
for rel in patch.get("files") or []:
|
|
target = root / rel
|
|
markers = [Path(rel).name]
|
|
if target.is_dir():
|
|
markers.append(Path(rel).parent.name)
|
|
if any(marker in body for marker in markers):
|
|
return True
|
|
if patch["id"] in body:
|
|
return True
|
|
if (
|
|
delivery.get("genesis")
|
|
and patch.get("genesis_env")
|
|
and patch["genesis_env"] in body
|
|
):
|
|
return True
|
|
if delivery.get("dockerfile_bake") and "ghcr.io/noonghunna/vllm-club3090" in body:
|
|
return True
|
|
return False
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Artifact-coverage helpers (extracted verbatim in behaviour).
|
|
# --------------------------------------------------------------------------
|
|
def is_artifact(path: Path) -> bool:
|
|
text = path.as_posix()
|
|
return (
|
|
"/patches/" in text
|
|
and "/patches/genesis/" not in text
|
|
and "/_pre-pr" not in text
|
|
and path.suffix in {".py", ".sh"}
|
|
)
|
|
|
|
|
|
def is_chat_template_artifact(path: Path) -> bool:
|
|
"""A vendored chat-template `.jinja` under a model's `vllm/patches/`
|
|
tree (CONTRACT-2b-i).
|
|
|
|
Kept SEPARATE from :func:`is_artifact` (which is behaviour-frozen for
|
|
the shipped `.py`/`.sh` overlay/sidecar orphan check) so the new class
|
|
is additive: the test discovers chat-template artifacts with this and
|
|
asserts each is owned by a `delivery_mechanism: chat_template` patch —
|
|
so a bad/regressed/re-vendored template can never ship with zero
|
|
attribution coverage."""
|
|
text = path.as_posix()
|
|
return (
|
|
"/patches/" in text
|
|
and "/patches/genesis/" not in text
|
|
and "/_pre-pr" not in text
|
|
and path.suffix in CHAT_TEMPLATE_ARTIFACT_SUFFIXES
|
|
)
|
|
|
|
|
|
def covered(path: Path, covered_files: Iterable[Path]) -> bool:
|
|
for entry in covered_files:
|
|
if entry.is_file() and path == entry:
|
|
return True
|
|
if entry.is_dir() and (path == entry or entry in path.parents):
|
|
return True
|
|
return False
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
# [C0] state machine (extracted verbatim).
|
|
# --------------------------------------------------------------------------
|
|
def c0_state(row: dict, tp: int, trust_ack: bool = False) -> str:
|
|
trc = row["requires_trust_remote_code"]
|
|
if trc in {"true", "unverified"} and not trust_ack:
|
|
return "needs-trust-remote-code-ack"
|
|
if tp not in set(row["valid_tp"]["tp_divisors"]):
|
|
return "engine-support-unknown"
|
|
if any(pin.get("loads") for pin in row["engine_pin"]):
|
|
return "engine-supported"
|
|
return "engine-support-unknown"
|