Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions loopx/capabilities/issue_fix/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
"""Public issue-fix capability boundaries."""
from __future__ import annotations

from .pr_description import build_issue_fix_pr_description
from .periodic_report import (
build_issue_fix_periodic_report_source,
issue_fix_periodic_report_source_adapter,
)
from .reward_memory import (
run_issue_fix_patch_planning_reward_memory,
run_issue_fix_reviewer_artifact_reward_memory,
)
from importlib import import_module
from typing import Any

# PR wait observation imports one owner submodule; it does not select report
# sources, PR descriptions or reward-memory workflows. Keep compatibility
# exports identical to their owners without importing them eagerly.
_EXPORTS = {
"build_issue_fix_pr_description": "pr_description",
"build_issue_fix_periodic_report_source": "periodic_report",
"issue_fix_periodic_report_source_adapter": "periodic_report",
"run_issue_fix_patch_planning_reward_memory": "reward_memory",
"run_issue_fix_reviewer_artifact_reward_memory": "reward_memory",
}


def __getattr__(name: str) -> Any:
module = _EXPORTS.get(name)
if module is None:
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
value = getattr(import_module(f".{module}", __name__), name)
globals()[name] = value
return value


def __dir__() -> list[str]:
return sorted(set(globals()) | set(__all__))

__all__ = [
"build_issue_fix_periodic_report_source",
Expand Down
154 changes: 75 additions & 79 deletions loopx/capabilities/reward_memory/__init__.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,80 @@
"""Provider-neutral reward-memory architecture contracts."""
from __future__ import annotations

from .architecture import (
build_reward_memory_architecture_packet,
build_reward_memory_route_packet,
pr_3237_regression_observation,
)
from .application import (
RewardMemoryFilteredRecallItem,
RewardMemoryRecallItem,
RewardMemoryRecallSession,
apply_reward_memory_recall,
build_active_reward_memory_record,
build_reward_memory_recall_request,
execute_reward_memory_recall,
normalize_reward_memory_provider_binding,
)
from .candidate_review import (
build_issue_fix_reward_memory_candidate,
build_reward_memory_candidate,
issue_fix_verified_contributor_candidate_fixture,
review_reward_memory_candidate,
)
from .codex_app_outcome import (
run_staged_codex_app_turn_outcome_ingest,
run_staged_codex_app_turn_outcome_ingest_fail_open,
stage_codex_app_turn_outcome_candidate,
stage_codex_app_turn_outcome_candidate_fail_open,
)
from .health import (
build_reward_memory_corpus_health_packet,
reward_memory_health_case,
)
from .ingestion import (
ingest_reward_memory_candidate,
normalize_reward_memory_standing_policy,
)
from .evaluation import run_reward_memory_evaluation
from .decision import (
RewardMemoryDecisionResult,
assess_reward_memory_decision,
run_reward_memory_decision,
)
from .dogfood import (
build_reward_memory_dogfood_batch,
build_reward_memory_dogfood_receipt,
build_reward_memory_operator_control,
)
from .memory_utility import (
MEMORY_UTILITY_OBSERVATION_SCHEMA_VERSION,
build_reward_memory_utility_observation,
reward_memory_application_receipt_id,
validate_reward_memory_utility_observation,
)
from .utility_reducer import (
MEMORY_UTILITY_PROJECTION_SCHEMA_VERSION,
MEMORY_UTILITY_REDUCER_VERSION,
UTILITY_MAX,
UTILITY_MIN,
build_reward_memory_utility_projection,
reduce_reward_memory_utility,
reduce_reward_memory_utility_observations,
reward_memory_utility_reducer_identity,
validate_reward_memory_utility_projection,
)
from .registry import (
build_reward_memory_corpus_registry_packet,
normalize_reward_memory_corpus,
semantic_preference_inventory_to_reward_corpora,
)
from .runtime_hooks import (
run_reward_memory_automatic_ingest_hook,
run_reward_memory_automatic_recall_hook,
)
from .read_authority import build_reward_memory_surface_read_authority_checkpoints
from .outcome_lifecycle import (
reconcile_pending_turn_outcome_ingests,
reconcile_pending_turn_outcome_ingests_fail_open,
run_configured_turn_outcome_ingest,
run_configured_turn_outcome_ingest_fail_open,
)
from importlib import import_module
from typing import Any

# Turn hooks import one owner submodule; they do not select evaluation, dogfood
# or Codex App staging. Keep compatibility exports identical to their owners
# without importing every reward-memory workflow when a submodule loads.
_EXPORTS = {
"build_reward_memory_architecture_packet": "architecture",
"build_reward_memory_route_packet": "architecture",
"pr_3237_regression_observation": "architecture",
"RewardMemoryFilteredRecallItem": "application",
"RewardMemoryRecallItem": "application",
"RewardMemoryRecallSession": "application",
"apply_reward_memory_recall": "application",
"build_active_reward_memory_record": "application",
"build_reward_memory_recall_request": "application",
"execute_reward_memory_recall": "application",
"normalize_reward_memory_provider_binding": "application",
"build_issue_fix_reward_memory_candidate": "candidate_review",
"build_reward_memory_candidate": "candidate_review",
"issue_fix_verified_contributor_candidate_fixture": "candidate_review",
"review_reward_memory_candidate": "candidate_review",
"run_staged_codex_app_turn_outcome_ingest": "codex_app_outcome",
"run_staged_codex_app_turn_outcome_ingest_fail_open": "codex_app_outcome",
"stage_codex_app_turn_outcome_candidate": "codex_app_outcome",
"stage_codex_app_turn_outcome_candidate_fail_open": "codex_app_outcome",
"build_reward_memory_corpus_health_packet": "health",
"reward_memory_health_case": "health",
"ingest_reward_memory_candidate": "ingestion",
"normalize_reward_memory_standing_policy": "ingestion",
"run_reward_memory_evaluation": "evaluation",
"RewardMemoryDecisionResult": "decision",
"assess_reward_memory_decision": "decision",
"run_reward_memory_decision": "decision",
"build_reward_memory_dogfood_batch": "dogfood",
"build_reward_memory_dogfood_receipt": "dogfood",
"build_reward_memory_operator_control": "dogfood",
"MEMORY_UTILITY_OBSERVATION_SCHEMA_VERSION": "memory_utility",
"build_reward_memory_utility_observation": "memory_utility",
"reward_memory_application_receipt_id": "memory_utility",
"validate_reward_memory_utility_observation": "memory_utility",
"MEMORY_UTILITY_PROJECTION_SCHEMA_VERSION": "utility_reducer",
"MEMORY_UTILITY_REDUCER_VERSION": "utility_reducer",
"UTILITY_MAX": "utility_reducer",
"UTILITY_MIN": "utility_reducer",
"build_reward_memory_utility_projection": "utility_reducer",
"reduce_reward_memory_utility": "utility_reducer",
"reduce_reward_memory_utility_observations": "utility_reducer",
"reward_memory_utility_reducer_identity": "utility_reducer",
"validate_reward_memory_utility_projection": "utility_reducer",
"build_reward_memory_corpus_registry_packet": "registry",
"normalize_reward_memory_corpus": "registry",
"semantic_preference_inventory_to_reward_corpora": "registry",
"run_reward_memory_automatic_ingest_hook": "runtime_hooks",
"run_reward_memory_automatic_recall_hook": "runtime_hooks",
"build_reward_memory_surface_read_authority_checkpoints": "read_authority",
"reconcile_pending_turn_outcome_ingests": "outcome_lifecycle",
"reconcile_pending_turn_outcome_ingests_fail_open": "outcome_lifecycle",
"run_configured_turn_outcome_ingest": "outcome_lifecycle",
"run_configured_turn_outcome_ingest_fail_open": "outcome_lifecycle",
}


def __getattr__(name: str) -> Any:
module = _EXPORTS.get(name)
if module is None:
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
value = getattr(import_module(f".{module}", __name__), name)
globals()[name] = value
return value


def __dir__() -> list[str]:
return sorted(set(globals()) | set(__all__))

__all__ = [
"build_reward_memory_architecture_packet",
Expand Down
31 changes: 31 additions & 0 deletions tests/test_cli_entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,37 @@ def test_turn_facade_preserves_every_export_owner_identity() -> None:
assert completed.returncode == 0, completed.stderr


def test_capability_hook_imports_defer_unselected_facade_exports() -> None:
script = """
from importlib import import_module
import sys

import loopx.capabilities.issue_fix.pr_wait_hook
import loopx.capabilities.reward_memory.turn_hooks

for name in (
"issue_fix.periodic_report",
"issue_fix.pr_description",
"issue_fix.reward_memory",
"reward_memory.codex_app_outcome",
"reward_memory.dogfood",
"reward_memory.evaluation",
):
assert "loopx.capabilities." + name not in sys.modules, name

from loopx.capabilities import issue_fix, reward_memory
for facade in (issue_fix, reward_memory):
assert set(facade._EXPORTS) == set(facade.__all__)
for name in facade.__all__:
value = getattr(facade, name)
owner = import_module("." + facade._EXPORTS[name], facade.__name__)
assert value is getattr(owner, name), name
assert name in dir(facade)
"""
completed = run_isolated_script(script)
assert completed.returncode == 0, completed.stderr


def test_quota_facade_lazy_exports_preserve_owner_identity() -> None:
script = """
from importlib import import_module
Expand Down
Loading