f946b0d0ca
gates / gates (push) Successful in 12s
From hub v0.112.0 a floor above the golden is served only with a declared
MinAgent, read from this CHANGELOG's newest `## vX.Y.Z` header. New fast,
blocking gate minagent_header_gate.py: that block must contain a line
starting `**MinAgent: X.Y.Z**`; prose, a code span or a non-bold mention
does not count (decoy test; red-proof F: relaxing the match to a body
mention fails test_decoy_body_mention_is_not_the_line).
Backfill: v0.233.0, v0.234.0, v0.235.0 and v0.236.0 carried no MinAgent
line. Each now reads `**MinAgent: 0.129.0** (unchanged)`, the value of the
nearest earlier header (v0.232.0). Proof it did not move: zero commits
under controller/internal/agentapi since 2026-09-01 (last: bb50e12,
2026-08-14), and the highest featureMinAgent entry is 0.129.0.
58 lines
2.2 KiB
Python
58 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""Tests for minagent_header_gate.py (R-470/R-472) — each case writes a CHANGELOG and runs the REAL gate.
|
|
|
|
Run from controller/: python3 scripts/test_minagent_header_gate.py
|
|
"""
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
SCRIPTS = os.path.dirname(os.path.abspath(__file__))
|
|
GATE = os.path.join(SCRIPTS, "minagent_header_gate.py")
|
|
|
|
|
|
def run(body):
|
|
with tempfile.NamedTemporaryFile("w", suffix=".md", delete=False, encoding="utf-8") as f:
|
|
f.write(body)
|
|
path = f.name
|
|
try:
|
|
env = dict(os.environ, MINAGENT_GATE_CHANGELOG=path)
|
|
p = subprocess.run([sys.executable, GATE], capture_output=True, text=True, env=env)
|
|
return p.returncode, p.stdout + p.stderr
|
|
finally:
|
|
os.unlink(path)
|
|
|
|
|
|
class MinAgentHeaderGateTest(unittest.TestCase):
|
|
def test_header_line_passes(self):
|
|
rc, out = run("## v0.239.0 — x (2026-09-13)\n\n**MinAgent: 0.129.0** (unchanged)\n\nbody\n\n## v0.238.1 — y\n")
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("v0.239.0 declares MinAgent 0.129.0", out)
|
|
|
|
def test_missing_line_fails_naming_the_header(self):
|
|
rc, out = run("## v0.239.0 — x (2026-09-13)\n\nbody\n\n## v0.238.1 — y\n\n**MinAgent: 0.129.0** (unchanged)\n")
|
|
self.assertEqual(rc, 1, out)
|
|
self.assertIn("v0.239.0", out)
|
|
|
|
def test_decoy_body_mention_is_not_the_line(self):
|
|
"""R-421: the word in prose, a code span, or a non-bold form is the LABEL without the FACT.
|
|
|
|
COMPANION RED-PROOF F (REPORT.md): relax MINAGENT_LINE_RE to a plain search for 'MinAgent'.
|
|
This test then passes the decoy and fails."""
|
|
decoy = ("## v0.239.0 — x (2026-09-13)\n\n"
|
|
"MinAgent is unchanged from the previous release, see `**MinAgent: 0.129.0**` there.\n"
|
|
"The agent requirement (MinAgent: 0.129.0) did not move.\n\n## v0.238.1 — y\n")
|
|
rc, out = run(decoy)
|
|
self.assertEqual(rc, 1, out)
|
|
|
|
def test_no_header_is_inconclusive(self):
|
|
rc, out = run("# CHANGELOG\n\nnothing released\n")
|
|
self.assertEqual(rc, 2, out)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|