Some checks failed
CI / lint (push) Successful in 55s
CI / notebooks-smoke (push) Successful in 2m54s
Deploy / changes (push) Successful in 24s
CI / test (push) Failing after 5m7s
Infra CI / zotero (push) Successful in 35s
Infra CI / docs (push) Successful in 55s
Infra CI / notebooks (push) Successful in 2m31s
Infra CI / api (push) Successful in 1m36s
Infra CI / bcda (push) Successful in 3m16s
Infra CI / llm (push) Successful in 1m57s
Deploy / notebooks (push) Has been skipped
Deploy / zotero (push) Has been skipped
Deploy / docs (push) Has been skipped
Infra CI / mc (push) Successful in 29s
Deploy / report (push) Has been cancelled
Deploy / llm (push) Has been cancelled
Deploy / mc (push) Has been cancelled
Deploy / bcda (push) Has been cancelled
Deploy / api (push) Has been cancelled
The seal skip treated a docket fully indexed under its seal as done forever, so attachment text extracted afterwards was never embedded: 16 backfilled dockets (~16k comments) had combined.md written and the index listed nothing. A sealed, complete docket is now relisted when any comment's combined.md is newer than its last complete index, and an explicitly named --docket is never skipped.
220 lines
6.9 KiB
Python
220 lines
6.9 KiB
Python
"""Exercise cli/llm.py's `index` seal-skip wiring: sealed/complete dockets
|
|
are excluded from the comment listing, and only pending seals are passed
|
|
through to be re-marked."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from typer.testing import CliRunner
|
|
|
|
from cli.llm import app
|
|
|
|
runner = CliRunner()
|
|
_STATS = {
|
|
"indexed": 0,
|
|
"skipped": 0,
|
|
"chunks": 0,
|
|
"fingerprint_skipped": 5,
|
|
"hash_skipped": 0,
|
|
"docket_complete": 0,
|
|
}
|
|
|
|
|
|
@patch("llm.index.extracted_since", return_value=False) # nothing new to index
|
|
@patch("llm.index._engine")
|
|
@patch(
|
|
"llm.index.docket_complete",
|
|
return_value={"CMS-2019-0111": "s1", "CMS-2020-0088": "old"},
|
|
)
|
|
@patch("llm.source.iter_comment_refs")
|
|
@patch("llm.pool.HostPool.from_config")
|
|
@patch("llm.index.index_refs")
|
|
@patch("conf.connect.bib")
|
|
@patch("llm.config.load")
|
|
def test_complete_sealed_dockets_are_not_listed(
|
|
mock_load,
|
|
mock_bib,
|
|
mock_index,
|
|
mock_pool,
|
|
mock_iter,
|
|
mock_complete,
|
|
_engine,
|
|
_since,
|
|
):
|
|
mock_load.return_value = MagicMock()
|
|
store = MagicMock()
|
|
store.sealed_dockets.return_value = {"CMS-2019-0111": "s1", "CMS-2020-0088": "s2"}
|
|
mock_bib.return_value = store
|
|
mock_iter.return_value = iter([])
|
|
mock_index.return_value = _STATS
|
|
|
|
result = runner.invoke(app, ["index"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
kwargs = mock_iter.call_args.kwargs
|
|
assert kwargs["skip_dockets"] == {"CMS-2019-0111"} # seal matches → skipped
|
|
ikw = mock_index.call_args.kwargs
|
|
assert ikw["sealed"] == {
|
|
"CMS-2020-0088": "s2"
|
|
} # re-sealed docket will be re-marked
|
|
assert ikw["mark_complete"] is True
|
|
assert "fp_skipped=5" in result.output
|
|
|
|
|
|
@patch("llm.index._engine")
|
|
@patch("llm.index.docket_complete", return_value={})
|
|
@patch("llm.source.iter_comment_refs")
|
|
@patch("llm.pool.HostPool.from_config")
|
|
@patch("llm.index.index_refs")
|
|
@patch("conf.connect.bib")
|
|
@patch("llm.config.load")
|
|
def test_force_and_limit_disable_skips_and_completion(
|
|
mock_load, mock_bib, mock_index, mock_pool, mock_iter, mock_complete, _engine
|
|
):
|
|
mock_load.return_value = MagicMock()
|
|
store = MagicMock()
|
|
store.sealed_dockets.return_value = {"CMS-2019-0111": "s1"}
|
|
mock_bib.return_value = store
|
|
mock_iter.return_value = iter([])
|
|
mock_index.return_value = _STATS
|
|
|
|
result = runner.invoke(app, ["index", "--force", "--limit", "5"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert mock_iter.call_args.kwargs["skip_dockets"] == set()
|
|
assert mock_index.call_args.kwargs["mark_complete"] is False
|
|
|
|
|
|
@patch("llm.index._engine")
|
|
@patch("llm.migrate.migrate")
|
|
@patch("llm.index.docket_complete", return_value={})
|
|
@patch("llm.source.iter_comment_refs")
|
|
@patch("llm.pool.HostPool.from_config")
|
|
@patch("llm.index.index_refs")
|
|
@patch("conf.connect.bib")
|
|
@patch("llm.config.load")
|
|
def test_migrate_runs_before_docket_complete_and_engine_is_reused(
|
|
mock_load,
|
|
mock_bib,
|
|
mock_index,
|
|
mock_pool,
|
|
mock_iter,
|
|
mock_complete,
|
|
mock_migrate,
|
|
mock_engine,
|
|
):
|
|
"""index_docket_state may not exist yet on the first sealed run."""
|
|
order: list[str] = []
|
|
mock_migrate.side_effect = lambda e: order.append("migrate")
|
|
mock_complete.side_effect = lambda e, c: (order.append("complete"), {})[1]
|
|
mock_load.return_value = MagicMock()
|
|
store = MagicMock()
|
|
store.sealed_dockets.return_value = {"CMS-2019-0111": "s1"}
|
|
mock_bib.return_value = store
|
|
mock_iter.return_value = iter([])
|
|
mock_index.return_value = _STATS
|
|
|
|
result = runner.invoke(app, ["index"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert order == ["migrate", "complete"]
|
|
mock_engine.assert_called_once() # one engine, shared
|
|
assert mock_migrate.call_args.args[0] is mock_engine.return_value
|
|
assert mock_complete.call_args.args[0] is mock_engine.return_value
|
|
assert mock_index.call_args.kwargs["engine"] is mock_engine.return_value
|
|
|
|
|
|
@patch("llm.index._engine")
|
|
@patch("llm.migrate.migrate")
|
|
@patch("llm.index.docket_complete", return_value={})
|
|
@patch("llm.source.iter_comment_refs")
|
|
@patch("llm.pool.HostPool.from_config")
|
|
@patch("llm.index.index_refs")
|
|
@patch("conf.connect.bib")
|
|
@patch("llm.config.load")
|
|
def test_force_touches_neither_engine_nor_migrate(
|
|
mock_load,
|
|
mock_bib,
|
|
mock_index,
|
|
mock_pool,
|
|
mock_iter,
|
|
mock_complete,
|
|
mock_migrate,
|
|
mock_engine,
|
|
):
|
|
mock_load.return_value = MagicMock()
|
|
store = MagicMock()
|
|
store.sealed_dockets.return_value = {"CMS-2019-0111": "s1"}
|
|
mock_bib.return_value = store
|
|
mock_iter.return_value = iter([])
|
|
mock_index.return_value = _STATS
|
|
|
|
result = runner.invoke(app, ["index", "--force"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
mock_engine.assert_not_called()
|
|
mock_migrate.assert_not_called()
|
|
mock_complete.assert_not_called()
|
|
assert mock_index.call_args.kwargs["engine"] is None
|
|
|
|
|
|
@patch("llm.index._engine")
|
|
@patch(
|
|
"llm.index.docket_complete",
|
|
return_value={"CMS-2020-0052": "s1", "CMS-2019-0111": "s1"},
|
|
)
|
|
@patch("llm.source.iter_comment_refs")
|
|
@patch("llm.pool.HostPool.from_config")
|
|
@patch("llm.index.index_refs")
|
|
@patch("conf.connect.bib")
|
|
@patch("llm.config.load")
|
|
def test_text_extracted_after_the_last_complete_index_relists_the_docket(
|
|
mock_load,
|
|
mock_bib,
|
|
mock_index,
|
|
mock_pool,
|
|
mock_iter,
|
|
mock_complete,
|
|
_engine,
|
|
tmp_path,
|
|
monkeypatch,
|
|
):
|
|
# 16 dockets had attachment text extracted after they were sealed and
|
|
# fully indexed; the seal skip hid the new text from the index.
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
root = tmp_path / "comments"
|
|
fresh = root / "CMS-2020-0052" / "CMS-2020-0052-1"
|
|
fresh.mkdir(parents=True)
|
|
(fresh / "combined.md").write_text("new attachment text")
|
|
stale = root / "CMS-2019-0111" / "CMS-2019-0111-1"
|
|
stale.mkdir(parents=True)
|
|
(stale / "combined.md").write_text("old")
|
|
old = (datetime.now(timezone.utc) - timedelta(days=30)).timestamp()
|
|
import os
|
|
|
|
os.utime(stale / "combined.md", (old, old))
|
|
monkeypatch.setattr("llm.source._default_root", lambda: root)
|
|
monkeypatch.setattr(
|
|
"llm.index.docket_indexed_at",
|
|
lambda engine, c: {
|
|
"CMS-2020-0052": datetime.now(timezone.utc) - timedelta(days=1),
|
|
"CMS-2019-0111": datetime.now(timezone.utc) - timedelta(days=1),
|
|
},
|
|
)
|
|
mock_load.return_value = MagicMock()
|
|
store = MagicMock()
|
|
store.sealed_dockets.return_value = {"CMS-2020-0052": "s1", "CMS-2019-0111": "s1"}
|
|
mock_bib.return_value = store
|
|
mock_iter.return_value = iter([])
|
|
mock_index.return_value = _STATS
|
|
|
|
result = runner.invoke(app, ["index"])
|
|
assert result.exit_code == 0, result.output
|
|
assert mock_iter.call_args.kwargs["skip_dockets"] == {"CMS-2019-0111"}
|
|
|
|
result = runner.invoke(app, ["index", "--docket", "CMS-2019-0111"])
|
|
assert result.exit_code == 0, result.output
|
|
assert "CMS-2019-0111" not in mock_iter.call_args.kwargs["skip_dockets"]
|