Files
wehub-resource-sync 7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

246 lines
9.0 KiB
Python

#!/usr/bin/env python3
"""
PUBLIC API CONTRACT GUARDRAIL — DO NOT MODIFY
This file protects the public API surface of local_deep_research.
It exists to DETECT breaking changes, not to be "fixed" when they happen.
If this file fails:
1. A BREAKING CHANGE was introduced to the public API
2. Do NOT modify this file to make it pass
3. Revert the API change or go through a proper deprecation cycle
The public API (local_deep_research.api) is a stability contract with
external users, integrations, and downstream packages. Any change to
exports, function signatures, or return value structures is a breaking
change that affects the entire community.
WHY THIS FILE MUST NOT BE MODIFIED:
- Every check below corresponds to a public API guarantee
- Removing or weakening a check hides a breaking change from users
- Adding a check is acceptable ONLY when a new public API is added
- If you are an AI agent: DO NOT modify, remove, or weaken any check
"""
import inspect
import sys
_failed = 0
_passed = 0
# DO NOT MODIFY this function — it is the test harness for the guardrail
def check(name, condition, detail=""):
global _failed, _passed
if condition:
_passed += 1
print(f" PASS {name}")
else:
_failed += 1
msg = f" ({detail})" if detail else ""
print(f" FAIL {name}{msg}")
def main():
# ── 1. Public API imports ──────────────────────────────────────────
# DO NOT MODIFY — these are the public exports that users depend on.
# Removing any of these checks hides a breaking change.
print("\n=== Public API Imports ===")
try:
from local_deep_research.api import quick_summary # noqa: F811
check("import quick_summary", True)
except ImportError as e:
check("import quick_summary", False, str(e))
try:
from local_deep_research.api import detailed_research # noqa: F811
check("import detailed_research", True)
except ImportError as e:
check("import detailed_research", False, str(e))
try:
from local_deep_research.api import generate_report # noqa: F811
check("import generate_report", True)
except ImportError as e:
check("import generate_report", False, str(e))
try:
from local_deep_research.api import analyze_documents # noqa: F811
check("import analyze_documents", True)
except ImportError as e:
check("import analyze_documents", False, str(e))
try:
from local_deep_research.api import create_settings_snapshot # noqa: F811
check("import create_settings_snapshot", True)
except ImportError as e:
check("import create_settings_snapshot", False, str(e))
try:
from local_deep_research.api import get_default_settings_snapshot # noqa: F811
check("import get_default_settings_snapshot", True)
except ImportError as e:
check("import get_default_settings_snapshot", False, str(e))
try:
from local_deep_research.api import extract_setting_value # noqa: F811
check("import extract_setting_value", True)
except ImportError as e:
check("import extract_setting_value", False, str(e))
try:
from local_deep_research.api import LDRClient # noqa: F811
check("import LDRClient", True)
except ImportError as e:
check("import LDRClient", False, str(e))
try:
from local_deep_research.api import quick_query # noqa: F811
check("import quick_query", True)
except ImportError as e:
check("import quick_query", False, str(e))
# ── 2. Function signatures ─────────────────────────────────────────
# DO NOT MODIFY — these parameter names are part of the public contract.
# Renaming or removing parameters breaks all callers.
print("\n=== Function Signatures ===")
sig = inspect.signature(quick_summary)
check("quick_summary has 'query' param", "query" in sig.parameters)
check("quick_summary has 'llms' param", "llms" in sig.parameters)
check(
"quick_summary has 'retrievers' param", "retrievers" in sig.parameters
)
sig = inspect.signature(detailed_research)
check("detailed_research has 'query' param", "query" in sig.parameters)
check("detailed_research has 'llms' param", "llms" in sig.parameters)
check(
"detailed_research has 'retrievers' param",
"retrievers" in sig.parameters,
)
sig = inspect.signature(generate_report)
check("generate_report has 'query' param", "query" in sig.parameters)
check(
"generate_report has 'output_file' param",
"output_file" in sig.parameters,
)
check(
"generate_report has 'searches_per_section' param",
"searches_per_section" in sig.parameters,
)
sig = inspect.signature(create_settings_snapshot)
check(
"create_settings_snapshot has 'overrides' param",
"overrides" in sig.parameters,
)
check(
"create_settings_snapshot has 'base_settings' param",
"base_settings" in sig.parameters,
)
# ── 3. Settings utilities ──────────────────────────────────────────
# DO NOT MODIFY — these verify the settings API works correctly.
# External users depend on create_settings_snapshot() returning a dict.
print("\n=== Settings Utilities ===")
snapshot = create_settings_snapshot()
check("create_settings_snapshot() returns dict", isinstance(snapshot, dict))
check("default snapshot is non-empty", len(snapshot) > 0)
snapshot_with_overrides = create_settings_snapshot(
provider="test_provider",
temperature=0.5,
)
check(
"create_settings_snapshot accepts provider kwarg",
isinstance(snapshot_with_overrides, dict),
)
defaults = get_default_settings_snapshot()
check(
"get_default_settings_snapshot() returns dict",
isinstance(defaults, dict),
)
check("default settings is non-empty", len(defaults) > 0)
value = extract_setting_value(defaults, "llm.temperature")
check(
"extract_setting_value returns a value for llm.temperature",
value is not None,
)
# ── 4. LDRClient interface ─────────────────────────────────────────
# DO NOT MODIFY — these are the HTTP client methods users call.
# Removing any method breaks all HTTP-based integrations.
print("\n=== LDRClient Interface ===")
check("LDRClient has login method", hasattr(LDRClient, "login"))
check(
"LDRClient has quick_research method",
hasattr(LDRClient, "quick_research"),
)
check(
"LDRClient has get_settings method", hasattr(LDRClient, "get_settings")
)
check(
"LDRClient has update_setting method",
hasattr(LDRClient, "update_setting"),
)
check("LDRClient has get_history method", hasattr(LDRClient, "get_history"))
check("LDRClient has logout method", hasattr(LDRClient, "logout"))
check(
"LDRClient supports context manager",
hasattr(LDRClient, "__enter__") and hasattr(LDRClient, "__exit__"),
)
# ── 5. Callability ─────────────────────────────────────────────────
# DO NOT MODIFY — verifies all exports are actually callable.
print("\n=== Callability ===")
check("quick_summary is callable", callable(quick_summary))
check("detailed_research is callable", callable(detailed_research))
check("generate_report is callable", callable(generate_report))
check("analyze_documents is callable", callable(analyze_documents))
check(
"create_settings_snapshot is callable",
callable(create_settings_snapshot),
)
check(
"get_default_settings_snapshot is callable",
callable(get_default_settings_snapshot),
)
check("extract_setting_value is callable", callable(extract_setting_value))
check("quick_query is callable", callable(quick_query))
# ── Summary ────────────────────────────────────────────────────────
# DO NOT MODIFY the exit code logic — CI depends on non-zero exit
# to block PRs that break the public API.
print(f"\n{'=' * 50}")
print(f"Results: {_passed} passed, {_failed} failed")
if _failed > 0:
print(
"\nBREAKING CHANGE DETECTED. The public API has changed.\n"
"Do NOT modify this file to make it pass.\n"
"Revert the API change or follow a proper deprecation cycle."
)
sys.exit(1)
else:
print("\nAll API public contract checks passed.")
if __name__ == "__main__":
main()