Skip to content

Commit 87f91a7

Browse files
committed
feat: use configs
1 parent 29d3373 commit 87f91a7

23 files changed

Lines changed: 415 additions & 123 deletions

‎app/boot/config.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
"""This module defines boot-time helpers that load YAML-backed configuration providers."""
22

3-
from app.boot.db import get_defaults_dir
3+
from functools import lru_cache
4+
from pathlib import Path
5+
46
from app.config.loader import YamlConfigProvider
57

68

9+
@lru_cache(maxsize=1)
710
def get_config_provider() -> YamlConfigProvider:
811
"""This function returns the shared YAML configuration provider instance."""
912

10-
return YamlConfigProvider(get_defaults_dir())
13+
defaults_dir = Path(__file__).resolve().parents[1] / "config" / "defaults"
14+
return YamlConfigProvider(defaults_dir)

‎app/boot/create_policy.py‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Boot-time helpers for normalized create-policy settings."""
2+
3+
from typing import Any
4+
5+
from app.boot.config import get_config_provider
6+
from app.core.contracts.errors import ErrorCode, ErrorDetail
7+
8+
9+
_SUPPORTED_GATES = ("schema", "semantic", "integrity")
10+
11+
12+
def get_create_policy_settings() -> dict[str, Any]:
13+
"""Return normalized create-policy settings from YAML config."""
14+
15+
policy = get_config_provider().get_create_policy()
16+
configured_gates = policy.get("gates") or list(_SUPPORTED_GATES)
17+
gates = [str(gate) for gate in configured_gates if str(gate) in _SUPPORTED_GATES]
18+
if "schema" not in gates:
19+
raise ValueError("create_policy.gates must include schema")
20+
return {"gates": gates}
21+
22+
23+
def validate_create_policy_settings() -> list[ErrorDetail]:
24+
"""Return structured config errors for unsupported create-policy settings."""
25+
26+
try:
27+
get_create_policy_settings()
28+
except ValueError as exc:
29+
return [ErrorDetail(code=ErrorCode.INTERNAL_ERROR, message=str(exc), field="create_policy.gates")]
30+
return []

‎app/boot/db.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@
33
import os
44
from pathlib import Path
55

6+
from app.boot.config import get_config_provider
67
from app.periphery.db.engine import get_engine
78
from app.periphery.db.session import get_session_factory
89

910

1011
def get_db_dsn() -> str:
1112
"""This function resolves the database DSN from environment configuration."""
1213

13-
dsn = os.getenv("MEMORY_DB_DSN")
14+
runtime = get_config_provider().get_runtime()
15+
database = runtime.get("database") or {}
16+
dsn_env = str(database.get("dsn_env", "MEMORY_DB_DSN"))
17+
dsn = os.getenv(dsn_env)
1418
if not dsn:
15-
raise RuntimeError("MEMORY_DB_DSN is not set")
19+
raise RuntimeError(f"{dsn_env} is not set")
1620
return dsn
1721

1822

‎app/boot/read_policy.py‎

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""Boot-time helpers for resolving YAML-backed read-policy settings."""
2+
3+
from copy import deepcopy
4+
from typing import Any
5+
6+
from app.boot.config import get_config_provider
7+
8+
9+
_DEFAULT_LIMITS = {
10+
"targeted": 8,
11+
"ambient": 12,
12+
}
13+
_DEFAULT_EXPAND = {
14+
"semantic_hops": 2,
15+
"include_problem_links": True,
16+
"include_fact_update_links": True,
17+
"include_association_links": True,
18+
"max_association_depth": 2,
19+
"min_association_strength": 0.25,
20+
}
21+
_DEFAULT_QUOTAS = {
22+
"targeted": {"direct": 4, "explicit": 3, "implicit": 1},
23+
"ambient": {"direct": 4, "explicit": 5, "implicit": 3},
24+
}
25+
_DEFAULT_RETRIEVAL = {
26+
"semantic_weight": 1.0,
27+
"keyword_weight": 1.0,
28+
"k_rrf": 20.0,
29+
}
30+
31+
32+
def get_read_settings() -> dict[str, Any]:
33+
"""Return normalized read settings from YAML-backed runtime and policy config."""
34+
35+
config_provider = get_config_provider()
36+
read_policy = config_provider.get_read_policy()
37+
runtime = config_provider.get_runtime()
38+
cli_defaults = runtime.get("cli") or {}
39+
limits = read_policy.get("limits") or {}
40+
expansion = read_policy.get("expansion") or {}
41+
quotas = read_policy.get("quotas") or {}
42+
weights = read_policy.get("weights") or {}
43+
fusion = read_policy.get("fusion") or {}
44+
45+
settings = {
46+
"default_mode": str(cli_defaults.get("default_mode", "targeted")),
47+
"include_global": bool(cli_defaults.get("include_global", True)),
48+
"limits_by_mode": {
49+
mode: int(limits.get(mode, fallback))
50+
for mode, fallback in _DEFAULT_LIMITS.items()
51+
},
52+
"expand": {
53+
"semantic_hops": int(expansion.get("semantic_hops", _DEFAULT_EXPAND["semantic_hops"])),
54+
"include_problem_links": bool(
55+
expansion.get("include_problem_links", _DEFAULT_EXPAND["include_problem_links"])
56+
),
57+
"include_fact_update_links": bool(
58+
expansion.get("include_fact_update_links", _DEFAULT_EXPAND["include_fact_update_links"])
59+
),
60+
"include_association_links": bool(
61+
expansion.get("include_association_links", _DEFAULT_EXPAND["include_association_links"])
62+
),
63+
"max_association_depth": int(
64+
expansion.get("max_association_depth", _DEFAULT_EXPAND["max_association_depth"])
65+
),
66+
"min_association_strength": float(
67+
expansion.get("min_association_strength", _DEFAULT_EXPAND["min_association_strength"])
68+
),
69+
},
70+
"quotas_by_mode": {
71+
mode: {
72+
bucket: int((quotas.get(mode) or {}).get(bucket, fallback))
73+
for bucket, fallback in defaults.items()
74+
}
75+
for mode, defaults in _DEFAULT_QUOTAS.items()
76+
},
77+
"retrieval": {
78+
"semantic_weight": float(weights.get("semantic", _DEFAULT_RETRIEVAL["semantic_weight"])),
79+
"keyword_weight": float(weights.get("keyword", _DEFAULT_RETRIEVAL["keyword_weight"])),
80+
"k_rrf": float(fusion.get("k_rrf", _DEFAULT_RETRIEVAL["k_rrf"])),
81+
},
82+
}
83+
return deepcopy(settings)
84+
85+
86+
def get_read_hydration_defaults() -> dict[str, Any]:
87+
"""Return the read defaults expected by CLI hydration."""
88+
89+
settings = get_read_settings()
90+
return {
91+
"default_mode": settings["default_mode"],
92+
"include_global": settings["include_global"],
93+
"limits_by_mode": deepcopy(settings["limits_by_mode"]),
94+
"expand": deepcopy(settings["expand"]),
95+
}
96+
97+
98+
def get_retrieval_defaults() -> dict[str, float]:
99+
"""Return normalized retrieval defaults for fusion and seed retrieval."""
100+
101+
return dict(get_read_settings()["retrieval"])
102+
103+
104+
def resolve_read_limit(*, mode: str, explicit_limit: int | None) -> int:
105+
"""Resolve the effective read limit from explicit payload or mode-based config."""
106+
107+
if explicit_limit is not None:
108+
return int(explicit_limit)
109+
settings = get_read_settings()
110+
return int(settings["limits_by_mode"].get(mode, _DEFAULT_LIMITS["targeted"]))
111+
112+
113+
def resolve_read_quotas(*, mode: str) -> dict[str, int]:
114+
"""Resolve the configured context-pack quotas for one read mode."""
115+
116+
settings = get_read_settings()
117+
quotas = settings["quotas_by_mode"].get(mode, settings["quotas_by_mode"]["targeted"])
118+
return {bucket: int(value) for bucket, value in quotas.items()}

‎app/boot/retrieval.py‎

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
11
"""This module defines boot-time helpers for retrieval repository wiring."""
22

3-
from app.boot.config import get_config_provider
4-
5-
6-
def get_retrieval_defaults() -> dict[str, float]:
7-
"""This function returns baseline retrieval defaults used by boot wiring."""
8-
9-
read_policy = get_config_provider().get_read_policy()
10-
weights = read_policy.get("weights") or {}
11-
fusion = read_policy.get("fusion") or {}
12-
return {
13-
"semantic_weight": float(weights.get("semantic", 1.0)),
14-
"keyword_weight": float(weights.get("keyword", 1.0)),
15-
"k_rrf": float(fusion.get("k_rrf", 20.0)),
16-
}
3+
from app.boot.read_policy import get_retrieval_defaults

‎app/boot/thresholds.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Boot-time helpers for normalized retrieval threshold settings."""
2+
3+
from app.boot.config import get_config_provider
4+
5+
6+
def get_threshold_settings() -> dict[str, float]:
7+
"""Return normalized retrieval thresholds from YAML config."""
8+
9+
thresholds = get_config_provider().get_thresholds()
10+
return {
11+
"semantic_threshold": float(thresholds.get("semantic_threshold", 0.0)),
12+
"keyword_threshold": float(thresholds.get("keyword_threshold", 0.0)),
13+
}

‎app/boot/update_policy.py‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Boot-time helpers for normalized update-policy settings."""
2+
3+
from typing import Any
4+
5+
from app.boot.config import get_config_provider
6+
from app.core.contracts.errors import ErrorCode, ErrorDetail
7+
8+
9+
_SUPPORTED_GATES = ("schema", "semantic", "integrity")
10+
11+
12+
def get_update_policy_settings() -> dict[str, Any]:
13+
"""Return normalized update-policy settings from YAML config."""
14+
15+
policy = get_config_provider().get_update_policy()
16+
configured_gates = policy.get("gates") or list(_SUPPORTED_GATES)
17+
gates = [str(gate) for gate in configured_gates if str(gate) in _SUPPORTED_GATES]
18+
if "schema" not in gates:
19+
raise ValueError("update_policy.gates must include schema")
20+
return {"gates": gates}
21+
22+
23+
def validate_update_policy_settings() -> list[ErrorDetail]:
24+
"""Return structured config errors for unsupported update-policy settings."""
25+
26+
try:
27+
get_update_policy_settings()
28+
except ValueError as exc:
29+
return [ErrorDetail(code=ErrorCode.INTERNAL_ERROR, message=str(exc), field="update_policy.gates")]
30+
return []

‎app/config/defaults/create_policy.yaml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,3 @@ gates:
33
- schema
44
- semantic
55
- integrity
6-
atomicity: true
7-
strict_create_evidence: true

‎app/config/defaults/runtime.yaml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# This file defines runtime defaults for database connectivity and execution mode.
22
database:
33
dsn_env: MEMORY_DB_DSN
4-
jobs:
5-
mode: in_process
64
cli:
75
default_mode: targeted
86
include_global: true

‎app/config/defaults/update_policy.yaml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ gates:
33
- schema
44
- semantic
55
- integrity
6-
atomicity: true

0 commit comments

Comments
 (0)