tools, instructions: Query-Log - reine Lesevorgänge nicht mehr in kb/log.md, Reconcile erzeugt den Katalog bei reinem Log-Zusatz nicht neu (#223); 10.1.1-beta.1
Files changed: - CHANGES.md - VERSION - docs/explanation/architecture.md - docs/reference/commands/catalog-and-log.md - docs/reference/commands/git.md - instructions/publish-cycle.md - instructions/session-setup.md - instructions/wiki-query/SKILL.md - tools/CONTRACT.md - tools/chemenu/commands/git_publish.py - tools/chemenu/commands/log_append.py - tools/chemenu/dist_templates/log.md - tools/chemenu/tests/test_git_publish.py Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
1 parent
c1ddefdc7f
commit
05c6697d3d
13 files changed
+140
-39
No files matched your search
+10
@@ -14,6 +14,16 @@ place only: `instructions/dev/version-parts.md` § The candidate model.
|
||||
|
||||
---
|
||||
|
||||
## 10.1.1-beta.1 - 2026-10-16 - Reine Lesevorgänge schreiben keinen Log-Eintrag mehr, und ein offener Log-Eintrag allein lässt den Katalog beim Abgleich unangetastet
|
||||
|
||||
**Author:** Torben Nehmer
|
||||
|
||||
<!-- wikitool:bumps -->
|
||||
- Reine Lesevorgänge schreiben keinen Log-Eintrag mehr, und ein offener Log-Eintrag allein lässt den Katalog beim Abgleich unangetastet
|
||||
<!-- /wikitool:bumps -->
|
||||
|
||||
---
|
||||
|
||||
## 10.1.0 - 2026-10-16 - Große PDFs und lange Quellen beim Ingest, vollständiger Export, Konverter-Tests gegen echte Dokumente
|
||||
|
||||
**Author:** Torben Nehmer
|
||||
|
||||
@@ -108,7 +108,7 @@ chemenu/
|
||||
├── kb/ # OUTPUT: compiled knowledge. A namespace, not a collection
|
||||
│ ├── CONTRACT.md # Collections, naming, tone, linking, provenance
|
||||
│ ├── index.md # Generated catalog *map*: counts and pointers
|
||||
│ ├── log.md # Generated chronological audit log
|
||||
│ ├── log.md # Generated audit log, in the order entries arrived
|
||||
│ ├── provenance.md # Generated raw-file reverse index
|
||||
│ ├── entities/ # COLLECTION.md + INDEX.md + areas below
|
||||
│ │ ├── codebases/
|
||||
|
||||
@@ -66,13 +66,13 @@ Append a formatted entry to `kb/log.md`.
|
||||
|
||||
**Synopsis**
|
||||
|
||||
- `wikitool log append --op ingest|query|lint|create|update|delete|rename|move --title "..." [--body "..."|--body-file path]`
|
||||
- `wikitool log append --op ingest|lint|create|update|delete|rename|move|query --title "..." [--body "..."|--body-file path]`
|
||||
|
||||
**Options**
|
||||
|
||||
```text
|
||||
--op <str> ingest|query|lint|create|update|delete|rename|move
|
||||
[required]
|
||||
--op <str> ingest|query|lint|create|update|delete|rename|move (query:
|
||||
legacy, no longer written by the stack) [required]
|
||||
--title <str> Brief description, e.g. a source path [required]
|
||||
--body <str> Optional multi-line details
|
||||
--body-file <path> Read the body from a file instead of --body
|
||||
@@ -90,6 +90,7 @@ tools/wikitool log append --op lint --title "2026-09-26" --body-file lint-summar
|
||||
|
||||
- Appends one entry to `kb/log.md`: a `## [YYYY-MM-DD] <op> | <title>` heading, the body if one is given, and a `---` separator.
|
||||
- Not idempotent: every successful run appends a new entry, including a repeated one.
|
||||
- `query` is a legacy value: older versions wrote one entry per read-only query. It is still accepted so existing logs and an instance's own instructions keep working, but the stack no longer writes it - a read is not an operation on the wiki.
|
||||
|
||||
**Properties**
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ tools/wikitool sync --confirm-rebase <token> # re-run after exit 42, once the
|
||||
**Behaviour**
|
||||
|
||||
- Fetches `<remote>/<branch>`, then: fast-forwards when only the remote moved; rebases the local commits on top when both sides moved but touched disjoint files; exits 42 (Rebase-Review Gate) when both sides touched the same file.
|
||||
- Files `wikitool` generates (`kb/index.md`, `kb/log.md`, `kb/provenance.md`, every `kb/**/INDEX.md`) never count as an overlap and never reach the gate. Where they are what stops git - uncommitted ones in the way of a fast-forward or rebase, or a rebase conflict in them - they are merged mechanically: `kb/log.md` becomes the incoming log plus the entries only this side appended, and the catalog and `kb/provenance.md` are regenerated from the merged pages and left as an uncommitted change. A reconcile git can do on its own is unchanged and regenerates nothing.
|
||||
- Files `wikitool` generates (`kb/index.md`, `kb/log.md`, `kb/provenance.md`, every `kb/**/INDEX.md`) never count as an overlap and never reach the gate. Where they are what stops git - uncommitted ones in the way of a fast-forward or rebase, or a rebase conflict in them - they are merged mechanically: `kb/log.md` becomes the incoming log plus the entries only this side appended, and the catalog and `kb/provenance.md` are regenerated from the merged pages and left as an uncommitted change. When only `kb/log.md` stood in the way - an open log entry, nothing else generated - the catalog is not rebuilt: the incoming one stays, and just the local entries are appended again. A reconcile git can do on its own is unchanged and regenerates nothing.
|
||||
- Uncommitted changes that no incoming commit touches do not stop a rebase: they are carried through it (`git rebase --autostash`) and come back unchanged.
|
||||
- Before anything is set aside, the working tree is stored as a commit under `refs/wikitool/reconcile-backup`. A successful reconcile drops it; a failed one restores the working tree and names the ref.
|
||||
- A refused call performs no rebase attempt and leaves the branch where it was.
|
||||
|
||||
@@ -30,7 +30,7 @@ consistent.
|
||||
3. **Append the audit entry** - one per operation:
|
||||
|
||||
```bash
|
||||
tools/wikitool log append --op ingest|query|lint|create|update|delete|rename|move \
|
||||
tools/wikitool log append --op ingest|lint|create|update|delete|rename|move \
|
||||
--title "<what>" --body "<outcome>"
|
||||
```
|
||||
|
||||
|
||||
@@ -88,7 +88,8 @@ the session instead of discovering the drift only at the very end.
|
||||
never commits and never pushes. Files `wikitool` generates are never a reason to stop: when the
|
||||
catalog or `kb/log.md` changed on both sides, `sync` keeps both sides' log entries and
|
||||
regenerates the catalog and `kb/provenance.md`, which it leaves as an uncommitted change for the
|
||||
next `publish`. Uncommitted work that the incoming commits do not touch stays where it is.
|
||||
next `publish`. An open log entry alone is no such case: the incoming catalog stays and only the
|
||||
entry is appended again. Uncommitted work that the incoming commits do not touch stays where it is.
|
||||
**Exit 42 (rebase-review)?** Same as any exit 42 - read the
|
||||
diff it prints, judge whether it conflicts with what you are about to do, summarize that to the
|
||||
user, then `tools/wikitool sync --confirm-rebase <token>` before continuing. See
|
||||
|
||||
@@ -12,10 +12,11 @@ description: Answers a question using the LLM wiki's compiled knowledge - read-o
|
||||
**Before the first `wikitool` call:** `instructions/session-setup.md`.
|
||||
|
||||
**Hard rule:** read-only with respect to wiki *content*. Never modify, hand-edit, or scaffold a
|
||||
page while answering. Two exceptions, both mechanical: step 7 (filing a valuable answer through
|
||||
`wikitool new`, never by hand) and step 8 (one audit entry via `wikitool log append`). If the
|
||||
wiki has no confident source, say so - per AGENTS.md's "never file an unsourced answer"
|
||||
invariant - rather than synthesizing a plausible-sounding answer from general knowledge.
|
||||
page while answering. One exception, mechanical: step 7 (filing a valuable answer through
|
||||
`wikitool new`, never by hand). A query writes no `kb/log.md` entry - a read changes nothing the
|
||||
wiki learned. If the wiki has no confident source, say so - per AGENTS.md's "never file an
|
||||
unsourced answer" invariant - rather than synthesizing a plausible-sounding answer from general
|
||||
knowledge.
|
||||
|
||||
## Steps
|
||||
|
||||
@@ -98,19 +99,16 @@ invariant - rather than synthesizing a plausible-sounding answer from general kn
|
||||
find again than a sentence in a chat log.
|
||||
|
||||
7. **File back what survived.** Scaffold it - `tools/wikitool new ...` - and follow
|
||||
`wiki-manage`. Never write the page by hand, and never file an answer no source backs.
|
||||
|
||||
8. **Log it.**
|
||||
|
||||
```bash
|
||||
tools/wikitool log append --op query --title "<question>" --body "<outcome>"
|
||||
```
|
||||
`wiki-manage`, which logs it as a `create` through `publish-cycle.md`. Never write the page by
|
||||
hand, and never file an answer no source backs.
|
||||
|
||||
## Decision points
|
||||
|
||||
- **Nothing found?** Try the structural query before concluding the wiki is silent - a page may
|
||||
exist under different words. Then say the wiki has no confident source, and offer to ingest
|
||||
one.
|
||||
one. If the user wants the gap kept, file it as an inbox item on their say-so:
|
||||
`tools/wikitool task new --inbox --title "<the question>"`. Without a configured tracker the
|
||||
offer stays in the chat. Never log it.
|
||||
- **The question asks for the wording** - "what exactly does rule 16:3e say", "which value is
|
||||
in table 4"? Find the page that carries the substance first (steps 2-3), then step 4's route
|
||||
to the passage. A paraphrase from the page is not the wording, and searching `raw/` is not a
|
||||
@@ -129,7 +127,7 @@ invariant - rather than synthesizing a plausible-sounding answer from general kn
|
||||
|
||||
## wikitool commands used
|
||||
|
||||
`search`, `log append`. If filing an answer back: `new`, `xref add`, `sources rebuild-index`,
|
||||
`search`. If filing an answer back: `new`, `xref add`, `sources rebuild-index`,
|
||||
`index rebuild`, and `publish` only if asked.
|
||||
|
||||
## Output
|
||||
|
||||
+3
-2
@@ -1035,7 +1035,7 @@ Append a formatted entry to `kb/log.md`.
|
||||
|
||||
**SYNOPSIS**
|
||||
|
||||
- `wikitool log append --op ingest|query|lint|create|update|delete|rename|move --title "..." [--body "..."|--body-file path]`
|
||||
- `wikitool log append --op ingest|lint|create|update|delete|rename|move|query --title "..." [--body "..."|--body-file path]`
|
||||
|
||||
**PROPERTIES**
|
||||
|
||||
@@ -1069,6 +1069,7 @@ Append a formatted entry to `kb/log.md`.
|
||||
|
||||
- Appends one entry to `kb/log.md`: a `## [YYYY-MM-DD] <op> | <title>` heading, the body if one is given, and a `---` separator.
|
||||
- Not idempotent: every successful run appends a new entry, including a repeated one.
|
||||
- `query` is a legacy value: older versions wrote one entry per read-only query. It is still accepted so existing logs and an instance's own instructions keep working, but the stack no longer writes it - a read is not an operation on the wiki.
|
||||
|
||||
**SEE ALSO**
|
||||
|
||||
@@ -2142,7 +2143,7 @@ Fetch `<remote>/<branch>` and bring the local branch up to date with it.
|
||||
**NOTES**
|
||||
|
||||
- Fetches `<remote>/<branch>`, then: fast-forwards when only the remote moved; rebases the local commits on top when both sides moved but touched disjoint files; exits 42 (Rebase-Review Gate) when both sides touched the same file.
|
||||
- Files `wikitool` generates (`kb/index.md`, `kb/log.md`, `kb/provenance.md`, every `kb/**/INDEX.md`) never count as an overlap and never reach the gate. Where they are what stops git - uncommitted ones in the way of a fast-forward or rebase, or a rebase conflict in them - they are merged mechanically: `kb/log.md` becomes the incoming log plus the entries only this side appended, and the catalog and `kb/provenance.md` are regenerated from the merged pages and left as an uncommitted change. A reconcile git can do on its own is unchanged and regenerates nothing.
|
||||
- Files `wikitool` generates (`kb/index.md`, `kb/log.md`, `kb/provenance.md`, every `kb/**/INDEX.md`) never count as an overlap and never reach the gate. Where they are what stops git - uncommitted ones in the way of a fast-forward or rebase, or a rebase conflict in them - they are merged mechanically: `kb/log.md` becomes the incoming log plus the entries only this side appended, and the catalog and `kb/provenance.md` are regenerated from the merged pages and left as an uncommitted change. When only `kb/log.md` stood in the way - an open log entry, nothing else generated - the catalog is not rebuilt: the incoming one stays, and just the local entries are appended again. A reconcile git can do on its own is unchanged and regenerates nothing.
|
||||
- Uncommitted changes that no incoming commit touches do not stop a rebase: they are carried through it (`git rebase --autostash`) and come back unchanged.
|
||||
- Before anything is set aside, the working tree is stored as a commit under `refs/wikitool/reconcile-backup`. A successful reconcile drops it; a failed one restores the working tree and names the ref.
|
||||
- A refused call performs no rebase attempt and leaves the branch where it was.
|
||||
|
||||
@@ -859,7 +859,9 @@ def rebase_review_token(remote: str, branch: str, local_before: str, remote_tip:
|
||||
#
|
||||
# The path below takes the generated files out of git's way and puts the result back
|
||||
# together mechanically: the log is the incoming version plus what only this side appended,
|
||||
# and the catalog and kb/provenance.md are regenerated from the merged pages. It runs only
|
||||
# and the catalog and kb/provenance.md are regenerated from the merged pages - unless the log
|
||||
# was the only generated file in the way: then the incoming catalog is already right for the
|
||||
# incoming pages, and only the log entries are appended again. It runs only
|
||||
# where git would otherwise have failed, so a reconcile that succeeds today is unchanged -
|
||||
# in particular it does not rebuild, because `index rebuild` stamps today's date into
|
||||
# kb/index.md and every `sync` would then end with a modified file.
|
||||
@@ -1049,22 +1051,34 @@ def _resolve_generated_conflicts() -> Optional[str]:
|
||||
|
||||
def _rebase_resolving_generated(remote_ref: str) -> tuple[bool, str, bool]:
|
||||
"""`git rebase --autostash <remote_ref>`, resolving each step whose conflicts are all in
|
||||
generated files. Returns (succeeded, detail, resolved anything). Any other stop is aborted,
|
||||
generated files. Returns (succeeded, detail, resolved a generated file other than the log - the
|
||||
log's own conflicts are merged without needing a rebuild). Any other stop is aborted,
|
||||
which also hands the autostash back."""
|
||||
result = _run(["git", "rebase", "--autostash", remote_ref], env=_NO_EDITOR)
|
||||
resolved = False
|
||||
while result.returncode != 0:
|
||||
if not _rebase_in_progress():
|
||||
return False, result.stderr, resolved
|
||||
listed = _run(["git", "diff", "--name-only", "--diff-filter=U", "-z"]).stdout
|
||||
unmerged = [path for path in listed.split("\0") if path]
|
||||
reason = _resolve_generated_conflicts()
|
||||
if reason:
|
||||
_run(["git", "rebase", "--abort"])
|
||||
return False, f"{reason}\n{result.stderr}", resolved
|
||||
resolved = True
|
||||
# A conflict in the log alone is resolved by the append-merge and leaves the catalog
|
||||
# as the incoming commits wrote it; only another generated file needs a rebuild.
|
||||
resolved = resolved or any(path != GENERATED_LOG for path in unmerged)
|
||||
result = _run(["git", "rebase", "--continue"], env=_NO_EDITOR)
|
||||
return True, "", resolved
|
||||
|
||||
|
||||
def append_log_suffix(log_suffix: bytes) -> None:
|
||||
"""Append what only this side added to kb/log.md back onto the incoming version."""
|
||||
if log_suffix:
|
||||
with (config.ROOT / GENERATED_LOG).open("ab") as log:
|
||||
log.write(log_suffix)
|
||||
|
||||
|
||||
def regenerate_generated(log_suffix: bytes = b"") -> None:
|
||||
"""Append `log_suffix` to kb/log.md, then rewrite the catalog and kb/provenance.md from the
|
||||
pages in the working tree - what `index rebuild` and `sources rebuild-index` write. The log
|
||||
@@ -1072,9 +1086,7 @@ def regenerate_generated(log_suffix: bytes = b"") -> None:
|
||||
from chemenu.commands.index_build import write_index
|
||||
from chemenu.commands.provenance_cmd import write_provenance_index
|
||||
|
||||
if log_suffix:
|
||||
with (config.ROOT / GENERATED_LOG).open("ab") as log:
|
||||
log.write(log_suffix)
|
||||
append_log_suffix(log_suffix)
|
||||
write_index(config.KB_DIR)
|
||||
write_provenance_index(config.KB_DIR, config.RAW_DIR)
|
||||
|
||||
@@ -1084,9 +1096,13 @@ def _around_generated(generated: list[str], operation, regenerate: bool) -> tupl
|
||||
(succeeded, detail, resolved generated conflicts) - and then either regenerate or put
|
||||
everything back. Returns (succeeded, detail, regenerated).
|
||||
|
||||
Regenerates when something generated was set aside or resolved, or when `regenerate` says
|
||||
both sides' commits touched a generated file - a textual merge of two catalogs can succeed
|
||||
and still be wrong. The backup ref is dropped on success and kept, and named, on any
|
||||
Regenerates the catalog and kb/provenance.md when a generated file other than kb/log.md
|
||||
was set aside or had a conflict resolved, or when `regenerate` says both sides' commits
|
||||
touched a generated file - a textual merge of two catalogs can succeed and still be wrong.
|
||||
When kb/log.md was all that stood in the way, the catalog the incoming commits brought is
|
||||
already right for the incoming pages, and only the local log entries are appended again:
|
||||
rebuilding would stamp today's date into kb/index.md and leave a changed file behind that
|
||||
no local change explains. The backup ref is dropped on success and kept, and named, on any
|
||||
failure."""
|
||||
backup = _back_up_working_tree()
|
||||
if backup is None:
|
||||
@@ -1105,9 +1121,11 @@ def _around_generated(generated: list[str], operation, regenerate: bool) -> tupl
|
||||
f"{detail.rstrip()}\nThe working tree was restored; as it stood before, it is also "
|
||||
f"kept at {BACKUP_REF} ({backup[:12]})."
|
||||
), False
|
||||
regenerated = bool(generated) or resolved or regenerate
|
||||
regenerated = any(path != GENERATED_LOG for path in generated) or resolved or regenerate
|
||||
if regenerated:
|
||||
regenerate_generated(aside.log_suffix)
|
||||
else:
|
||||
append_log_suffix(aside.log_suffix)
|
||||
_run(["git", "update-ref", "-d", BACKUP_REF])
|
||||
return True, "", regenerated
|
||||
|
||||
@@ -1119,7 +1137,8 @@ class ReconcileOutcome:
|
||||
"up-to-date", "fast-forwarded", "local-ahead", "rebased", "needs-review", "conflict".
|
||||
The first three are the ways the fetch can fail; `detail` then carries the remote's URL.
|
||||
`regenerated` says the catalog and kb/provenance.md were rewritten afterwards and are an
|
||||
uncommitted change now."""
|
||||
uncommitted change now. It stays False when only kb/log.md was set aside: its local entries
|
||||
are appended again and the catalog is the incoming one."""
|
||||
status: str
|
||||
pulled_commits: list[str] = field(default_factory=list)
|
||||
overlap_files: list[str] = field(default_factory=list)
|
||||
@@ -1421,8 +1440,11 @@ def apply_reconcile(outcome: ReconcileOutcome, remote: str, branch: str, command
|
||||
"what stops git - uncommitted ones in the way of a fast-forward or rebase, or a rebase "
|
||||
"conflict in them - they are merged mechanically: `kb/log.md` becomes the incoming log "
|
||||
"plus the entries only this side appended, and the catalog and `kb/provenance.md` are "
|
||||
"regenerated from the merged pages and left as an uncommitted change. A reconcile git "
|
||||
"can do on its own is unchanged and regenerates nothing.",
|
||||
"regenerated from the merged pages and left as an uncommitted change. When only "
|
||||
"`kb/log.md` stood in the way - an open log entry, nothing else generated - the "
|
||||
"catalog is not rebuilt: the incoming one stays, and just the local entries are "
|
||||
"appended again. A reconcile git can do on its own is unchanged and regenerates "
|
||||
"nothing.",
|
||||
"Uncommitted changes that no incoming commit touches do not stop a rebase: they are "
|
||||
"carried through it (`git rebase --autostash`) and come back unchanged.",
|
||||
"Before anything is set aside, the working tree is stored as a commit under "
|
||||
|
||||
@@ -55,7 +55,7 @@ def ingests_since_last_lint(entries: list[tuple[str, str, str]]) -> int:
|
||||
path="log append",
|
||||
summary="Append a formatted entry to `kb/log.md`.",
|
||||
synopsis=(cli_contract.Variant(
|
||||
usage="log append --op ingest|query|lint|create|update|delete|rename|move "
|
||||
usage="log append --op ingest|lint|create|update|delete|rename|move|query "
|
||||
'--title "..." [--body "..."|--body-file path]',
|
||||
),),
|
||||
properties=cli_contract.Properties(
|
||||
@@ -68,6 +68,9 @@ def ingests_since_last_lint(entries: list[tuple[str, str, str]]) -> int:
|
||||
"Appends one entry to `kb/log.md`: a `## [YYYY-MM-DD] <op> | <title>` heading, the body "
|
||||
"if one is given, and a `---` separator.",
|
||||
"Not idempotent: every successful run appends a new entry, including a repeated one.",
|
||||
"`query` is a legacy value: older versions wrote one entry per read-only query. It is "
|
||||
"still accepted so existing logs and an instance's own instructions keep working, but "
|
||||
"the stack no longer writes it - a read is not an operation on the wiki.",
|
||||
),
|
||||
failures=(
|
||||
cli_contract.Failure(
|
||||
@@ -94,7 +97,9 @@ def ingests_since_last_lint(entries: list[tuple[str, str, str]]) -> int:
|
||||
),
|
||||
))
|
||||
def log_append(
|
||||
op: str = typer.Option(..., "--op", help="|".join(VALID_OPS)),
|
||||
op: str = typer.Option(
|
||||
..., "--op", help="|".join(VALID_OPS) + " (query: legacy, no longer written by the stack)",
|
||||
),
|
||||
title: str = typer.Option(..., "--title", help="Brief description, e.g. a source path"),
|
||||
body: str = typer.Option("", "--body", help="Optional multi-line details"),
|
||||
body_file: Optional[Path] = typer.Option(None, "--body-file", help="Read the body from a file instead of --body"),
|
||||
|
||||
@@ -13,6 +13,6 @@ Each entry records what happened, when, and with what result.
|
||||
---
|
||||
```
|
||||
|
||||
Operation types: `ingest`, `query`, `lint`, `create`, `update`, `delete`
|
||||
Operation types: `ingest`, `lint`, `create`, `update`, `delete`, `rename`, `move`
|
||||
|
||||
---
|
||||
@@ -1662,6 +1662,69 @@ def test_case_1_on_sync_leaves_the_regenerated_catalog_uncommitted(wiki_repo):
|
||||
cwd=wiki_repo).returncode != 0 # dropped on success
|
||||
|
||||
|
||||
def _log_only_entry(root, title="a question"):
|
||||
"""What a read-only query used to leave behind: one appended log entry, nothing else."""
|
||||
with (root / "kb/log.md").open("a", encoding="utf-8", newline="\n") as log:
|
||||
log.write("\n" + format_log_entry("query", title, today="2026-10-06"))
|
||||
|
||||
|
||||
def _backup_ref_exists(root):
|
||||
return subprocess.run(["git", "show-ref", "--verify", "-q", git_publish.BACKUP_REF],
|
||||
cwd=root).returncode == 0
|
||||
|
||||
|
||||
def _assert_catalog_is_the_incoming_one(root):
|
||||
"""kb/index.md and kb/provenance.md are byte for byte what origin/main holds."""
|
||||
check = _check_tree(root)
|
||||
for path in ("kb/index.md", "kb/provenance.md"):
|
||||
assert (root / path).read_bytes() == (check / path).read_bytes(), path
|
||||
|
||||
|
||||
def test_an_open_log_entry_alone_does_not_regenerate_the_catalog_on_a_fast_forward(wiki_repo):
|
||||
writer = _clone_writer(wiki_repo)
|
||||
_writer_ingest(writer, "Writer")
|
||||
_log_only_entry(wiki_repo)
|
||||
|
||||
outcome = reconcile("origin", "main", None)
|
||||
|
||||
assert (outcome.status, outcome.regenerated) == ("fast-forwarded", False)
|
||||
assert _status(wiki_repo).split() == ["M", "kb/log.md"]
|
||||
_assert_catalog_is_the_incoming_one(wiki_repo)
|
||||
assert _logged_titles(wiki_repo) == ["Base", "Writer", "a question"]
|
||||
assert not _backup_ref_exists(wiki_repo)
|
||||
|
||||
|
||||
def test_an_open_log_entry_alone_does_not_regenerate_the_catalog_on_a_rebase(wiki_repo):
|
||||
"""A stranded commit that touches no generated file, an open log entry, and an ingest that
|
||||
landed meanwhile: rebased, the catalog stays the incoming one, the log keeps both."""
|
||||
writer = _clone_writer(wiki_repo)
|
||||
_writer_ingest(writer, "Writer")
|
||||
(wiki_repo / "local.md").write_text("local\n", encoding="utf-8")
|
||||
_commit_all(wiki_repo, "stranded, touches no generated file")
|
||||
_log_only_entry(wiki_repo)
|
||||
|
||||
outcome = reconcile("origin", "main", None)
|
||||
|
||||
assert (outcome.status, outcome.regenerated) == ("rebased", False)
|
||||
assert _status(wiki_repo).split() == ["M", "kb/log.md"]
|
||||
_assert_catalog_is_the_incoming_one(wiki_repo)
|
||||
assert _logged_titles(wiki_repo) == ["Base", "Writer", "a question"]
|
||||
assert (wiki_repo / "local.md").is_file()
|
||||
assert not _backup_ref_exists(wiki_repo)
|
||||
|
||||
|
||||
def test_an_open_log_entry_plus_an_uncommitted_page_still_regenerates(wiki_repo):
|
||||
"""The catalog was locally changed too, so it is set aside and has to be rebuilt."""
|
||||
writer = _clone_writer(wiki_repo)
|
||||
_writer_ingest(writer, "Writer")
|
||||
_ingest(wiki_repo, "Local")
|
||||
|
||||
outcome = reconcile("origin", "main", None)
|
||||
|
||||
assert (outcome.status, outcome.regenerated) == ("fast-forwarded", True)
|
||||
_assert_generated_current(wiki_repo)
|
||||
|
||||
|
||||
def test_case_2_two_committed_ingests_rebase_without_the_review_gate(wiki_repo):
|
||||
writer = _clone_writer(wiki_repo)
|
||||
_writer_ingest(writer, "Writer")
|
||||
|
||||
Reference in new issue
Block a user