Skip to content

Commit c7f5937

Browse files
committed
✨ (scripts): Enforce exact == operator on the core SDK pin
1 parent 43d098a commit c7f5937

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

scripts/generate_example_metadata.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,14 @@ def rewrite_python_manifest(path: Path, sdk: PythonSdk) -> bool:
193193
text = path.read_text(encoding="utf-8")
194194

195195
def _sub(match: re.Match[str]) -> str:
196+
# Normalize the operator to exact ``==``. The core SDK pin must never be a
197+
# floor/open range (AAASM-4704 and the repo's "never a bare >=" rule),
198+
# so a bump self-heals a drifted operator; the --check audit enforces the
199+
# same invariant. The regex still captures ``op`` so a non-``==`` pin is
200+
# matched and rewritten.
196201
indent = match.group("indent")
197-
op = match.group("op")
198202
tail = match.group("tail")
199-
return f'{indent}"{sdk.package}{op}{sdk.version}"{tail}'
203+
return f'{indent}"{sdk.package}=={sdk.version}"{tail}'
200204

201205
new_text = _PY_PIN_RE.sub(_sub, text)
202206
return _write_if_changed(path, new_text)
@@ -755,7 +759,7 @@ def process_prereq_rows(repo_root: Path, versions: SdkVersions) -> list[Path]:
755759
# exactly ``@agent-assembly/sdk``; the go id is exactly
756760
# ``github.com/ai-agent-assembly/go-sdk`` followed by whitespace.
757761
_PY_PIN_AUDIT_RE = re.compile(
758-
r"(?<![\w/@.-])agent-assembly(?:==|>=|~=|<=|!=|<|>)(?P<ver>[^\"'\s,]+)"
762+
r"(?<![\w/@.-])agent-assembly(?P<op>==|>=|~=|<=|!=|<|>)(?P<ver>[^\"'\s,]+)"
759763
)
760764
_NODE_PIN_AUDIT_RE = re.compile(r'"@agent-assembly/sdk"\s*:\s*"(?P<ver>[^"]+)"')
761765
_GO_PIN_AUDIT_RE = re.compile(
@@ -816,6 +820,30 @@ def _audit_pins(repo_root: Path, versions: SdkVersions) -> list[str]:
816820
return problems
817821

818822

823+
# The core SDK pin must be exact (``==``): a floor (``>=``) or open range lets a
824+
# resolver pull a future major and silently break an example (AAASM-4704, and the
825+
# repo's own "never a bare >=" rule). The version-drift audit above only checks
826+
# the version token, so this pass enforces the operator separately. Python
827+
# manifests are the only core-SDK pins that carry an operator — node pins are a
828+
# bare ``"<version>"`` string and go pins are a bare ``go.mod`` version.
829+
def _audit_py_operator(repo_root: Path, versions: SdkVersions) -> list[str]:
830+
"""Report every python core-SDK pin whose operator is not exact (``==``)."""
831+
832+
problems: list[str] = []
833+
for path in _globbed(repo_root, _PY_PIN_GLOBS):
834+
for lineno, line in _audit_lines(path):
835+
if EXEMPT_MARKER in line:
836+
continue
837+
match = _PY_PIN_AUDIT_RE.search(line)
838+
if match and match.group("op") != "==":
839+
rel = path.relative_to(repo_root)
840+
problems.append(
841+
f"{rel}:{lineno}: uses {match.group('op')!r} operator on the "
842+
f"core SDK pin, expected '=='"
843+
)
844+
return problems
845+
846+
819847
def _audit_prose(repo_root: Path, versions: SdkVersions) -> list[str]:
820848
"""Report every README/doc prose line whose SDK version drifts from the SoT.
821849
@@ -854,7 +882,9 @@ def audit(repo_root: Path, versions: SdkVersions) -> list[str]:
854882
"""Return every drifted SDK-version literal as a sorted ``file:line`` list."""
855883

856884
return sorted(
857-
_audit_pins(repo_root, versions) + _audit_prose(repo_root, versions)
885+
_audit_pins(repo_root, versions)
886+
+ _audit_py_operator(repo_root, versions)
887+
+ _audit_prose(repo_root, versions)
858888
)
859889

860890

0 commit comments

Comments
 (0)