cli.py's typer._click.core.format_help patch was applied a second time outside the try/except that exists to let a future typer without typer._click degrade to plain Click help instead of crashing on import. That second, unconditional line referenced two names the failed import never defines, so the exact case the fallback exists for raised NameError on every invocation instead. Removed; a subprocess test with a targeted import hook (not sys.modules poisoning, which breaks typer itself, and not importlib.reload, which would stay green against the bug) pins that the fallback now actually falls back. The new command's cli_contract record promised kb/concepts/<Name>.md and kb/sources/Source - <Name>.md - both types have since grown a layout: that files a page under a subtype-computed subdirectory, the same rule an entity or a project already follows. Notes for concept and source now name the subdirectory and where it comes from; comparison was checked against its type-spec and left alone. Also found and fixed: new source's example line omitted source_type, fidelity and authority, so it could never succeed as written. A new test reads each variant's note out of the record and checks the written path against the pattern it promises, instead of against a path re-typed into the test - which is what let the existing per-type path tests stay green through this exact drift. tools/CONTRACT.md regenerated via `wikitool docs contract --apply`; pytest (1550), docs verify and instructions verify all green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
1 parent
b8ed8bd610
commit
6c0ebcc4f0
7 files changed
+240
-13
No files matched your search
+48
-1
@@ -59,7 +59,7 @@ concern - readable here, never shipped as something to parse.
|
||||
|
||||
---
|
||||
|
||||
## 7.1.0-beta.28 - 2026-09-26 - gates.md and a run_budget comment name kb pages by title, not by a path that moved
|
||||
## 7.1.0-beta.30 - 2026-09-26 - new: concept/source record notes name their layout-computed subdirectory; source usage names its required fields (Gitea #150)
|
||||
|
||||
**Author:** Torben Nehmer
|
||||
|
||||
@@ -97,8 +97,55 @@ concern - readable here, never shipped as something to parse.
|
||||
- Command records: three more mismatches from #142 aligned to code
|
||||
- docs contract: the merged-stream test pins its own ON FAILURE line
|
||||
- gates.md and a run_budget comment name kb pages by title, not by a path that moved
|
||||
- cli.py: removed a stale duplicate help-patch line outside the typer._click fallback's try (Gitea #148)
|
||||
- new: concept/source record notes name their layout-computed subdirectory; source usage names its required fields (Gitea #150)
|
||||
<!-- /wikitool:bumps -->
|
||||
|
||||
### new: concept/source record notes name their layout-computed subdirectory; source usage names its required fields (Gitea #150)
|
||||
|
||||
The `new`-command's `cli_contract` record promised `kb/concepts/<Name>.md` and
|
||||
`kb/sources/Source - <Name>.md` for the `concept` and `source` variants - flat, with no
|
||||
subdirectory. Both type-specs have carried a `layout:` for a while (`concept_type`/`source_type`
|
||||
picks the area, same rule an entity or a project already follows), so the actual path is
|
||||
`kb/concepts/<subdir>/<Name>.md` and `kb/sources/<subdir>/Source - <Name>.md`. Nothing wrote a
|
||||
page to the wrong place - `new` computes the path itself - but the record is exactly what an
|
||||
agent reads to find one afterwards, and it was wrong: `instructions/gates.md` named two concept
|
||||
pages by their old flat path (fixed above) with the record itself as the plausible source of that
|
||||
assumption. Both notes now name the subdirectory and where it comes from; `comparison`'s note was
|
||||
checked against `types/comparison.md` and left alone; it genuinely has no `layout:`.
|
||||
|
||||
Found in the same pass: `new source`'s example line omitted `source_type` (required, no default
|
||||
since #66) and `fidelity`/`authority` (enforced by `new` itself since #67), so copying it verbatim
|
||||
always failed. It now names all three.
|
||||
|
||||
The new test in `tools/chemenu/tests/test_new_page.py` reads each variant's note out of the
|
||||
record itself and turns it into the path pattern it promises, then checks what `new` actually
|
||||
wrote against that pattern - coupled to the note text, not to a path re-typed into the test, which
|
||||
is what let the existing per-type path tests stay green through this exact drift. A companion test
|
||||
asserts every `Writes \`kb/...\`` variant has a case, so a future variant without one is caught
|
||||
here instead of silently going unchecked. `tools/CONTRACT.md` regenerated via
|
||||
`wikitool docs contract --apply`.
|
||||
|
||||
### cli.py: removed a stale duplicate help-patch line outside the typer._click fallback's try (Gitea #148)
|
||||
|
||||
The `typer._click.core.Command.format_help` patch was applied twice: once inside a
|
||||
`try/except (ImportError, AttributeError)` meant to let a future typer without `typer._click`
|
||||
degrade to Click's own plain help instead of crashing every invocation, and once more on the next
|
||||
module-level line, unconditionally. Whenever the `try` actually failed, that second line referenced
|
||||
two names the failed import never defined and raised `NameError` at import time - the exact crash
|
||||
the fallback exists to prevent, on every single `wikitool` call. Typer 0.27.2 still has the module,
|
||||
so nothing showed it in practice; the line was pure dead weight until the day it wasn't. Removed,
|
||||
so the patch is applied exactly where the `try` already applies it.
|
||||
|
||||
The new regression test drives `chemenu.cli` in a subprocess with a `builtins.__import__` hook
|
||||
that raises only for `typer._click.core` imported from `chemenu.cli`/`__main__`, then checks that
|
||||
`wikitool search -h` still exits 0 with Click's own plain help. Two more direct ways to simulate
|
||||
the missing module were tried and rejected: `sys.modules['typer._click.core'] = None` also breaks
|
||||
typer's own lazy import of `typer._click.decorators` inside `get_help_option`, so `-h` fails
|
||||
regardless of what `cli.py` does; `importlib.reload(chemenu.cli)` reruns the module in the same
|
||||
`__dict__`, so the names from the first, real import survive and the broken line runs
|
||||
successfully - a test built that way would stay green against the exact bug it exists to catch.
|
||||
|
||||
### gates.md and a run_budget comment name kb pages by title, not by a path that moved
|
||||
|
||||
`instructions/gates.md` pointed at `kb/concepts/Mass-Update Gate.md` and
|
||||
|
||||
Reference in new issue
Block a user