fix(miner,convo_miner): close remaining wing-name normalization gaps (#1194)

Two follow-ups against the review on this PR:

1. ``miner.load_config`` no-yaml fallback was returning the raw dirname
   as the wing, while ``cmd_init`` writes ``topics_by_wing`` under the
   normalized slug. A hyphenated project mined without a ``mempalace.yaml``
   file silently lost every topic tunnel — same key-miss class as #1194,
   just down the no-yaml branch (raised by Qodo on this PR).

2. ``convo_miner`` was applying the lower/replace rule inline at one
   call site. Now folded through ``normalize_wing_name`` so all wing-slug
   producers — ``cmd_init``, ``room_detector_local``, ``miner.load_config``
   fallback, ``convo_miner`` — share a single source of truth. No
   behavior change for any input; pure consolidation.

Added ``test_load_config_no_yaml_normalizes_hyphenated_wing`` to lock
the fallback path to the normalized slug — fails on develop without
the miner change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Igor Lins e Silva
2026-04-27 02:50:12 -03:00
committed by igorls
parent b7f0a8af01
commit 3bebef1503
3 changed files with 30 additions and 2 deletions
+3 -1
View File
@@ -394,7 +394,9 @@ def mine_convos(
convo_path = Path(convo_dir).expanduser().resolve()
if not wing:
wing = convo_path.name.lower().replace(" ", "_").replace("-", "_")
from .config import normalize_wing_name
wing = normalize_wing_name(convo_path.name)
files = scan_convos(convo_dir)
if limit > 0:
+9 -1
View File
@@ -286,7 +286,15 @@ def load_config(project_dir: str) -> dict:
if legacy_path.exists():
config_path = legacy_path
else:
wing_name = resolved_project_dir.name
from .config import normalize_wing_name
# Normalize the dirname-derived fallback wing the same way
# ``cmd_init`` and ``room_detector_local`` do — otherwise a
# hyphenated project mined without a yaml file lands under a
# raw-name wing while ``topics_by_wing`` was keyed under the
# normalized slug, silently dropping every topic tunnel
# (the no-yaml branch of issue #1194).
wing_name = normalize_wing_name(resolved_project_dir.name)
print(
f" No mempalace.yaml found in {resolved_project_dir} "
f"— using auto-detected defaults (wing='{wing_name}'). "
+18
View File
@@ -67,6 +67,24 @@ def test_load_config_uses_defaults_when_yaml_missing():
shutil.rmtree(tmpdir)
def test_load_config_no_yaml_normalizes_hyphenated_wing():
"""Fallback wing name is normalized so it matches topics_by_wing keys.
Regression for the no-yaml branch of #1194: ``cmd_init`` writes
``topics_by_wing`` under the normalized slug, so the miner's
fallback wing must use the same normalization or the tunnel lookup
misses every key for hyphenated dirnames.
"""
parent = tempfile.mkdtemp()
try:
project_root = Path(parent) / "my-cool-app"
project_root.mkdir()
config = load_config(str(project_root))
assert config["wing"] == "my_cool_app"
finally:
shutil.rmtree(parent)
def test_scan_project_skips_mempalace_generated_files():
with tempfile.TemporaryDirectory() as tmpdir:
project_root = Path(tmpdir).resolve()