18ae28f918
Chemenu kompiliert Rohnotizen zu einem verlinkten, quellengebundenen Wiki: raw/ -> types/ + tools/ -> kb/ -> reports/. Was mechanisch ist, macht tools/wikitool; was Urteil braucht, macht ein Agent unter Contracts, deren Grenzen in Code durchgesetzt sind statt im Prompt. Dieser Commit ist der Startpunkt der oeffentlichen Historie. Die vorherige Entwicklung fand in einer privaten Instanz statt und ist nicht Teil dieses Repositorys; ihre Erzaehlung steht vollstaendig in CHANGES.md, das mit 44 Eintraegen von 0.1.0 bis 2.1.0 erhalten geblieben ist. Der mitgelieferte Korpus ist ein Testbett und eine Demo: 170 Seiten ueber den Stack selbst - Gates, Lint, Versionierung, Suche, das Wiki-Muster. Er dokumentiert das Werkzeug mit den eigenen Mitteln des Werkzeugs. Lizenz: AGPL-3.0 fuer den Stack (tools/, types/), CC-BY-4.0 fuer die Inhalte. Die Grenze zwischen beiden ist der Dateiplan, den dist export berechnet - siehe NOTICE.
78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
from chemenu.commands.log_append import (
|
|
format_log_entry,
|
|
ingests_since_last_lint,
|
|
log_status,
|
|
parse_log_entries,
|
|
)
|
|
|
|
|
|
def test_log_entry_format_matches_convention():
|
|
entry = format_log_entry("ingest", "raw/notes/gateway.example.net.md", "Some details.", today="2026-08-02")
|
|
assert entry == (
|
|
"## [2026-08-02] ingest | raw/notes/gateway.example.net.md\n"
|
|
"\n"
|
|
"Some details.\n"
|
|
"\n"
|
|
"---\n"
|
|
)
|
|
|
|
|
|
def test_log_entry_without_body_has_no_blank_body_block():
|
|
entry = format_log_entry("query", "What projects use MQTT?", "", today="2026-08-02")
|
|
assert entry == "## [2026-08-02] query | What projects use MQTT?\n\n---\n"
|
|
|
|
|
|
def test_parse_log_entries_reads_date_op_and_title_in_file_order():
|
|
text = (
|
|
"# Wiki Log\n\n"
|
|
"## [2026-08-01] ingest | raw/notes/a.md\n\n---\n\n"
|
|
"## [2026-08-02] lint | Lint Report 2026-08-02.md\n\n---\n"
|
|
)
|
|
assert parse_log_entries(text) == [
|
|
("2026-08-01", "ingest", "raw/notes/a.md"),
|
|
("2026-08-02", "lint", "Lint Report 2026-08-02.md"),
|
|
]
|
|
|
|
|
|
def test_ingests_since_last_lint_resets_on_a_lint_entry():
|
|
entries = [
|
|
("2026-08-01", "ingest", "a.md"),
|
|
("2026-08-02", "ingest", "b.md"),
|
|
("2026-08-03", "lint", "Lint Report.md"),
|
|
("2026-08-04", "ingest", "c.md"),
|
|
]
|
|
assert ingests_since_last_lint(entries) == 1
|
|
|
|
|
|
def test_ingests_since_last_lint_counts_from_the_start_when_never_linted():
|
|
entries = [
|
|
("2026-08-01", "ingest", "a.md"),
|
|
("2026-08-02", "query", "What is X?"),
|
|
("2026-08-03", "ingest", "b.md"),
|
|
]
|
|
assert ingests_since_last_lint(entries) == 2
|
|
|
|
|
|
def test_log_status_reports_zero_with_no_log_file(tmp_path, monkeypatch, capsys):
|
|
import chemenu.config as config
|
|
|
|
monkeypatch.setattr(config, "LOG_FILE", tmp_path / "log.md")
|
|
log_status()
|
|
assert "No wiki/log.md yet" in capsys.readouterr().out
|
|
|
|
|
|
def test_log_status_warns_at_the_ten_ingest_threshold(tmp_path, monkeypatch, capsys):
|
|
import chemenu.config as config
|
|
|
|
log_file = tmp_path / "log.md"
|
|
body = "".join(
|
|
format_log_entry("ingest", f"raw/notes/{i}.md", today="2026-08-01") for i in range(10)
|
|
)
|
|
log_file.write_text(body, encoding="utf-8")
|
|
monkeypatch.setattr(config, "LOG_FILE", log_file)
|
|
|
|
log_status()
|
|
out = capsys.readouterr().out
|
|
assert "Ingests since last lint: 10" in out
|
|
assert "Threshold reached" in out
|