mirror of
https://github.com/Imbad0202/academic-research-skills.git
synced 2026-09-14 13:51:17 +08:00
a25ada2812
* feat(lint): #491 defrift lock for Phase Boundary enforcement sentence + SETUP parity + manifest gap Three pieces, all follow-ups from the 2026-07-04 harness-retirement pass: 1. check_v3_9_2_phase_boundary.py gains invariant 4: every Bucket A block's enforcement paragraph must carry the canonical sentence verbatim (CANONICAL_ENFORCEMENT, version-matched v3.9.2/v3.9.4; per-file tails free). The previous copy went factually stale repo-wide for a month with no lint noticing (B4-F01) — this converts 25 hand-synced copies into one lock. +7 mutation tests incl. the exact stale-sentence regression case. 2. New check_setup_cross_model_parity.py (+6 tests): SETUP en/zh-TW must carry the same ARS_CROSS_MODEL example values and every value must exist in the canonical lineup doc (the B4-F02 drift class). Fail-closed on zero extracted examples. Wired into spec-consistency.yml. 3. _ci_pytest_manifest.toml gains v3.9.4-temporal-verification — the test whose absence made PR #490 local-green/CI-red (bibliography_agent sha256 pin only checked in CI). Local manifest now catches it: 58 -> 60 entries. Verification: manifest drift guard green; full manifest 60/60 green; phase-boundary lint green on repo baseline; personal-boundary 993 files 0 violations. Closes #491 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBdGUAb184hmuiRiWAm4A9 * fix(lint): scope canonical membership to model tables only (codex review P1) The membership check accepted any backticked token in the canonical doc, so a SETUP example reverting to gpt-5.4-pro would false-pass on the legacy-accepted NOTE — the exact B4-F02 drift class the lint exists to catch. Membership now parses only the "API ID" table columns; ids in surrounding prose do not count. +3 tests incl. the literal legacy-revert regression case + table-parser fail-closed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBdGUAb184hmuiRiWAm4A9 * fix(lint): exclude wildcard prefix tokens from canonical model ids (codex re-review P2) The compat table's "any non-`gpt-*`/`gemini-*` id" prose sits in an API ID column, leaking glob patterns into the allowed set. Globs are prefix patterns, not model ids — filtered, with a regression test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBdGUAb184hmuiRiWAm4A9 * refactor(lint): /simplify pass — dedupe update guidance, shared module loader, cross-refs - Simplification: the "update + sweep" maintenance guidance was triplicated inside the defrift lint itself with a hand-typed file count; now stated once in the error message with len(BUCKET_A_AGENTS) interpolated, and the mirror wording corrected (mirrors follow mechanically via check_agents_mirror_sync.py, not by hand-sweeping). - Reuse (R1, option b): CANONICAL_ENFORCEMENT stays lint-local by design (factual status prose, not a behavioral firm rule) — rationale in the constant comment + "Related mechanisms" cross-ref in firm_rules.md so the two canonical-sync mechanisms know about each other. - Reuse (R2): tests/test_helpers.py gains load_module_from_path(); both new test files use it (6 pre-existing local copies migrate at next edit). - Efficiency note: workflow comment marks the 2x pytest.yml overlap as the accepted manifest pattern. All lints + 21 tests + full 60-entry manifest green; firm-rules sync green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBdGUAb184hmuiRiWAm4A9 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
122 lines
5.0 KiB
Python
122 lines
5.0 KiB
Python
"""Unit tests for check_setup_cross_model_parity.py (#491 fold-in)."""
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from tests.test_helpers import load_module_from_path, run_script
|
|
|
|
SCRIPT = Path(__file__).resolve().parent / "check_setup_cross_model_parity.py"
|
|
|
|
EN_OK = 'export ARS_CROSS_MODEL="gpt-5.5"\n# or: export ARS_CROSS_MODEL="gemini-3.1-pro-preview"\n'
|
|
ZH_OK = EN_OK
|
|
CANONICAL_OK = (
|
|
"| Model | API ID | Provider |\n"
|
|
"|-------|--------|----------|\n"
|
|
"| GPT-5.5 | `gpt-5.5` | OpenAI |\n"
|
|
"| Gemini 3.1 Pro | `gemini-3.1-pro-preview` | Google |\n"
|
|
"\n"
|
|
"(`gpt-5.4` / `gpt-5.4-pro` remain accepted for existing setups.)\n"
|
|
)
|
|
|
|
|
|
def _load_module():
|
|
return load_module_from_path("check_setup_cross_model_parity", SCRIPT)
|
|
|
|
|
|
class SetupCrossModelParityTests(unittest.TestCase):
|
|
|
|
def test_repo_baseline_passes(self) -> None:
|
|
"""The committed SETUP + canonical doc state must pass."""
|
|
result = run_script(SCRIPT)
|
|
self.assertEqual(result.returncode, 0, msg=f"stderr: {result.stderr}")
|
|
self.assertIn("PASSED", result.stdout)
|
|
|
|
def test_clean_fixture_passes(self) -> None:
|
|
module = _load_module()
|
|
self.assertEqual(module.check(EN_OK, ZH_OK, CANONICAL_OK), [])
|
|
|
|
def test_en_zh_drift_fails(self) -> None:
|
|
"""One-sided edit (the B4-F02 shape: en updated, zh-TW forgotten)."""
|
|
module = _load_module()
|
|
zh_stale = 'export ARS_CROSS_MODEL="gpt-5.4-pro"\n'
|
|
errors = module.check(EN_OK, zh_stale, CANONICAL_OK)
|
|
self.assertTrue(any("drift" in e for e in errors), msg=f"errors: {errors}")
|
|
|
|
def test_legacy_id_in_prose_note_does_not_count(self) -> None:
|
|
"""codex P1 regression (PR #492): `gpt-5.4-pro` is backticked in the
|
|
canonical doc's legacy-accepted NOTE but absent from the model tables —
|
|
a SETUP example reverting to it must FAIL, not pass on the note."""
|
|
module = _load_module()
|
|
stale = 'export ARS_CROSS_MODEL="gpt-5.4-pro"\n'
|
|
errors = module.check(stale, stale, CANONICAL_OK)
|
|
self.assertTrue(
|
|
any("gpt-5.4-pro" in e and "not in" in e for e in errors),
|
|
msg=f"errors: {errors}",
|
|
)
|
|
|
|
def test_canonical_table_parse_fails_closed(self) -> None:
|
|
"""No 'API ID' table in the canonical doc = parser stale = error."""
|
|
module = _load_module()
|
|
errors = module.check(EN_OK, ZH_OK, "prose only, `gpt-5.5` backticked")
|
|
self.assertTrue(
|
|
any("parser went stale" in e for e in errors), msg=f"errors: {errors}"
|
|
)
|
|
|
|
def test_compat_table_column_counts(self) -> None:
|
|
"""Ids in the compat table's 'Example API ID(s)' column are members."""
|
|
module = _load_module()
|
|
canonical = CANONICAL_OK + (
|
|
"\n| Provider | Example API ID(s) | Endpoint |\n"
|
|
"|----------|-------------------|----------|\n"
|
|
"| DeepSeek | `deepseek-v4-pro` | https://api.deepseek.com/v1 |\n"
|
|
)
|
|
ids = module.canonical_model_ids(canonical)
|
|
self.assertIn("deepseek-v4-pro", ids)
|
|
self.assertNotIn("gpt-5.4-pro", ids)
|
|
|
|
def test_wildcard_prefix_tokens_are_not_ids(self) -> None:
|
|
"""codex P2 regression (PR #492): the compat table's "any
|
|
non-`gpt-*`/`gemini-*` id" prose sits in an API ID column — globs are
|
|
prefix patterns, not model ids, and a SETUP example of `gpt-*` must
|
|
fail, not pass on the leaked token."""
|
|
module = _load_module()
|
|
canonical = CANONICAL_OK + (
|
|
"\n| Provider | Example API ID(s) | Endpoint |\n"
|
|
"|----------|-------------------|----------|\n"
|
|
"| Any OpenAI-compatible | any non-`gpt-*`/`gemini-*` id | any |\n"
|
|
)
|
|
self.assertNotIn("gpt-*", module.canonical_model_ids(canonical))
|
|
glob_setup = 'export ARS_CROSS_MODEL="gpt-*"\n'
|
|
errors = module.check(glob_setup, glob_setup, canonical)
|
|
self.assertTrue(
|
|
any("gpt-*" in e and "not in" in e for e in errors),
|
|
msg=f"errors: {errors}",
|
|
)
|
|
|
|
def test_unknown_model_fails(self) -> None:
|
|
"""Example naming a model outside the canonical lineup."""
|
|
module = _load_module()
|
|
bad = 'export ARS_CROSS_MODEL="gpt-9.9-imaginary"\n'
|
|
errors = module.check(bad, bad, CANONICAL_OK)
|
|
self.assertTrue(
|
|
any("gpt-9.9-imaginary" in e and "canonical" in e for e in errors),
|
|
msg=f"errors: {errors}",
|
|
)
|
|
|
|
def test_zero_examples_fails_closed(self) -> None:
|
|
"""Regex-went-stale / block-removed must be an error, not a pass."""
|
|
module = _load_module()
|
|
errors = module.check("no examples here", ZH_OK, CANONICAL_OK)
|
|
self.assertTrue(
|
|
any("Fail-closed" in e for e in errors), msg=f"errors: {errors}"
|
|
)
|
|
|
|
def test_commented_example_lines_are_extracted(self) -> None:
|
|
"""`# or:` alternates count — they are user-pasteable examples too."""
|
|
module = _load_module()
|
|
ids = module.extract_ids(EN_OK)
|
|
self.assertEqual(ids, ["gpt-5.5", "gemini-3.1-pro-preview"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|