From 95f637491e6d1d9ad57c33967dae3f5a57c15f38 Mon Sep 17 00:00:00 2001 From: m3taversal Date: Sat, 4 Apr 2026 15:46:47 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20Ganymede=20review=20=E2=80=94=20explicit?= =?UTF-8?q?=20staging,=20push=20after=20commit,=20challenged=5Fby=20recipr?= =?UTF-8?q?ocal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three fixes from Ganymede's review of extract-time-connection: 1. Replace git add -A with explicit file staging in _reciprocal_edges 2. Push to origin/main immediately after commit (survive batch-extract reset) 3. RECIPROCAL_EDGE_MAP: challenges→challenged_by (not symmetric) Added challenged_by to REWEAVE_EDGE_FIELDS, EDGE_FIELDS, EDGE_WEIGHTS Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/merge.py | 33 ++++++++++++++++++++++++++++----- lib/search.py | 1 + reweave.py | 2 +- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lib/merge.py b/lib/merge.py index a3a0873..3714d39 100644 --- a/lib/merge.py +++ b/lib/merge.py @@ -390,7 +390,16 @@ async def _cherry_pick_onto_main(branch: str) -> tuple[bool, str]: await _git("branch", "-D", clean_branch) -REWEAVE_EDGE_FIELDS = ("supports", "challenges", "depends_on", "related", "reweave_edges") +REWEAVE_EDGE_FIELDS = ("supports", "challenges", "challenged_by", "depends_on", "related", "reweave_edges") + +# When A supports B, B also supports A (approximately symmetric). +# When A challenges B, B is challenged_by A (NOT symmetric — direction matters). +RECIPROCAL_EDGE_MAP = { + "supports": "supports", + "challenges": "challenged_by", + "related": "related", + "depends_on": "related", # A depends_on B → B is related to A (not symmetric) +} def _parse_yaml_frontmatter(text: str) -> tuple[dict | None, str, str]: @@ -1143,6 +1152,7 @@ async def _reciprocal_edges(main_sha: str, branch_sha: str): return reciprocals_added = 0 + modified_files = set() for claim_path in new_claims: full_path = config.MAIN_WORKTREE / claim_path if not full_path.exists(): @@ -1179,18 +1189,31 @@ async def _reciprocal_edges(main_sha: str, branch_sha: str): continue # Add reciprocal edge: target now has field: [new_claim_slug] - if _add_edge_to_file(target_file, field, claim_slug): + reciprocal_type = RECIPROCAL_EDGE_MAP.get(field, "related") + if _add_edge_to_file(target_file, reciprocal_type, claim_slug): reciprocals_added += 1 + modified_files.add(str(target_file)) if reciprocals_added > 0: - # Commit the reciprocal edges - await _git("add", "-A", cwd=str(config.MAIN_WORKTREE)) + # Stage only the files we modified (never git add -A in automation) + for f in modified_files: + await _git("add", f, cwd=str(config.MAIN_WORKTREE)) rc, out = await _git( "commit", "-m", f"reciprocal edges: {reciprocals_added} edges from {len(new_claims)} new claims", cwd=str(config.MAIN_WORKTREE), ) if rc == 0: - logger.info("reciprocal_edges: %d edges added across %d new claims", reciprocals_added, len(new_claims)) + # Push immediately — batch-extract-50.sh does reset --hard origin/main + # every 15 min, which destroys unpushed local commits + push_rc, push_out = await _git( + "push", "origin", "main", + cwd=str(config.MAIN_WORKTREE), + timeout=30, + ) + if push_rc == 0: + logger.info("reciprocal_edges: %d edges pushed to main (%d new claims)", reciprocals_added, len(new_claims)) + else: + logger.warning("reciprocal_edges: push failed (commit is local only): %s", push_out[:200]) else: logger.warning("reciprocal_edges: commit failed: %s", out[:200]) diff --git a/lib/search.py b/lib/search.py index 8796f6d..c579d5d 100644 --- a/lib/search.py +++ b/lib/search.py @@ -236,6 +236,7 @@ def graph_expand(seed_paths: list[str], repo_root: Path | None = None, """ EDGE_WEIGHTS = { "challenges": 1.5, + "challenged_by": 1.5, "depends_on": 1.25, "supports": 1.0, "related": 1.0, diff --git a/reweave.py b/reweave.py index 8d9d07c..81d53c0 100644 --- a/reweave.py +++ b/reweave.py @@ -46,7 +46,7 @@ QDRANT_COLLECTION = os.environ.get("QDRANT_COLLECTION", "teleo-claims") FORGEJO_URL = os.environ.get("FORGEJO_URL", "http://localhost:3000") EMBED_DIRS = ["domains", "core", "foundations", "decisions", "entities"] -EDGE_FIELDS = ("supports", "challenges", "depends_on", "related") +EDGE_FIELDS = ("supports", "challenges", "challenged_by", "depends_on", "related") WIKI_LINK_RE = re.compile(r"\[\[([^\]]+)\]\]") # Thresholds (from calibration data — Mar 28)