diff --git a/src/java_codebase_rag/cli.py b/src/java_codebase_rag/cli.py index 5ca4cca6..c49f21db 100644 --- a/src/java_codebase_rag/cli.py +++ b/src/java_codebase_rag/cli.py @@ -104,11 +104,38 @@ def _emit_reprocess_selective_tty(*, mode: str) -> None: print("Skipped: vectors (use `java-codebase-rag reprocess --vectors-only` or `reprocess` to refresh)") +def _reprocess_success_message(mode: str | None, payload: dict[str, Any]) -> str: + """Concise message for a successful reprocess. + + Prefers an explicit ``message`` set by the pipeline (e.g. the graph-only- + install note from ``run_refresh_pipeline``); otherwise derives from the + selective mode. Mirrors ``init``/``increment``, which emit a one-line + success payload rather than re-dumping captured subprocess logs. + """ + explicit = payload.get("message") + if isinstance(explicit, str) and explicit: + return explicit + if mode == "vectors": + return "reprocess completed (vectors only; graph not rebuilt)" + if mode == "graph": + return "reprocess completed (graph only; vectors not rebuilt)" + return "reprocess completed" + + def _emit_reprocess_outcome(payload: dict[str, Any], *, selective_tty_mode: str | None = None) -> None: - if payload.get("success") and selective_tty_mode and sys.stdout.isatty(): + if not payload.get("success"): + # Failure: emit the full payload so captured subprocess stdout/stderr + # (cocoindex/graph logs) survive for debugging. + _emit(payload) + return + # Success: the progress renderer / stderr already surfaced the phase logs, + # so emit a concise structured payload (matching init/increment) instead of + # re-dumping them as JSON noise. In a TTY the partial modes additionally + # print a one-line Rebuilt/Skipped summary. + if selective_tty_mode and sys.stdout.isatty(): _emit_reprocess_selective_tty(mode=selective_tty_mode) return - _emit(payload) + _emit({"success": True, "message": _reprocess_success_message(selective_tty_mode, payload)}) _PIPELINE_SEP = "\u00b7" diff --git a/tests/fixtures/cli_progress_stdout/reprocess_quiet_success.stdout.txt b/tests/fixtures/cli_progress_stdout/reprocess_quiet_success.stdout.txt index 58fc3262..bbfc5eea 100644 --- a/tests/fixtures/cli_progress_stdout/reprocess_quiet_success.stdout.txt +++ b/tests/fixtures/cli_progress_stdout/reprocess_quiet_success.stdout.txt @@ -1 +1 @@ -{"exit_code": 0, "graph_exit_code": 0, "graph_stderr": "", "graph_stdout": "", "message": null, "optimize_error": null, "phases_run": ["vectors", "graph"], "stderr": "", "stdout": "", "success": true} +{"message": "reprocess completed", "success": true} diff --git a/tests/package/test_cli_progress_stdout_invariant.py b/tests/package/test_cli_progress_stdout_invariant.py index e842f12e..1731e10c 100644 --- a/tests/package/test_cli_progress_stdout_invariant.py +++ b/tests/package/test_cli_progress_stdout_invariant.py @@ -251,7 +251,7 @@ def test_cli_lifecycle_stdout_invariant_init_increment_reprocess_when_cocoindex( inc_payload = json.loads(r_inc.stdout) assert inc_payload == { "success": True, - "message": "increment completed (Lance only; graph may be stale — see stderr)", + "message": "increment completed (Lance + graph updated)", } r_rep = _run_cli( @@ -260,9 +260,7 @@ def test_cli_lifecycle_stdout_invariant_init_increment_reprocess_when_cocoindex( ) assert r_rep.returncode == 0, r_rep.stderr + r_rep.stdout rep_payload = json.loads(r_rep.stdout) - assert rep_payload.get("success") is True - assert isinstance(rep_payload.get("stdout"), str) - assert isinstance(rep_payload.get("graph_stderr"), str) + assert rep_payload == {"success": True, "message": "reprocess completed"} def test_pipeline_footer_reflects_exception_before_propagate(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: diff --git a/tests/package/test_java_codebase_rag_cli.py b/tests/package/test_java_codebase_rag_cli.py index dde95bd9..6b5b5921 100644 --- a/tests/package/test_java_codebase_rag_cli.py +++ b/tests/package/test_java_codebase_rag_cli.py @@ -979,7 +979,7 @@ def isatty(self) -> bool: ) assert rc == 0 payload = json.loads(nout.getvalue()) - assert payload["phases_run"] == ["vectors"] + assert payload == {"success": True, "message": "reprocess completed (vectors only; graph not rebuilt)"} def test_reprocess_graph_only_skips_vectors( @@ -1009,7 +1009,7 @@ def fake_graph(**_kwargs: object) -> subprocess.CompletedProcess[str]: ["reprocess", "--source-root", str(tmp_path), "--index-dir", str(idx), "--graph-only"], ) assert rc == 0 - assert json.loads(out.getvalue())["phases_run"] == ["graph"] + assert json.loads(out.getvalue()) == {"success": True, "message": "reprocess completed (graph only; vectors not rebuilt)"} def test_reprocess_mutually_exclusive_flags_rejected(tmp_path: Path) -> None: