Skip to content

fix(wiki): enforce frontmatter normalization and governance contract on all write paths - #112

Merged
cdeust merged 1 commit into
mainfrom
fix/wiki-write-path-governance
Jul 14, 2026
Merged

fix(wiki): enforce frontmatter normalization and governance contract on all write paths#112
cdeust merged 1 commit into
mainfrom
fix/wiki-write-path-governance

Conversation

@cdeust

@cdeust cdeust commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Closes #110

(Initialement empilée sur #109 ; rebasée sur main après son merge en squash — diff net d'un seul commit.)

Mécanisme

Analyse des 8 call sites contournants : tous écrivent des pages complètes (jamais de fragments), aucun ne doit légitimement échapper à la normalisation — mais plusieurs contournent la gouvernance délibérément (stubs de redirect, pages générées PRD/findings/référence, réécritures de liens). D'où la séparation :

  1. Normalisation : déplacée inconditionnellement dans wiki_store.write_page (mode != "append") — le point d'étranglement partagé. Ferme la classe de corruption pour tout appelant, présent et futur. Import infra→core suivant l'exception documentée préexistante du sous-système wiki (wiki_layout, wiki_sync).
  2. Gouvernance : reste la responsabilité exclusive de write_governed_page ; les 8 contournements restent délibérés. Docstring mensongère (« the ONLY function that may call write_page ») corrigée.
  3. Bug réel corrigé en chemin : write_governed_page avalait UnclosedFrontmatterError (sous-classe de ValueError) dans son except (ValueError, OSError) générique — contrat documenté cassé. Ré-levée explicite ajoutée, attrapée par le test préexistant.
  4. Garde-fou exécutable : tests_py/architecture/test_write_page_call_sites.py — scan regex de mcp_server/ diffé contre une liste blanche auditée par fichier ; prouvé qu'il échoue sur un bypass injecté artificiellement (puis retiré).

Tests

  • Corruption title: title: persistée canonique via 2 des 8 chemins contournants (wiki_adr, wiki_link) ; append_section inchangé.
  • Baseline 481 → 484 passed (3 nouveaux tests), 0 régression ; re-validé post-rebase (8 tests ciblés + ruff format/check propres, 0.15.20).

Limites connues

Garde-fou par comptage par fichier (pas par ligne) — le modèle de menace principal est un nouveau fichier contournant ; corruption des tests wiki_adr/wiki_link injectée par seed (leur génération réelle ne la produit pas) — prouve la frontière d'enforcement. Dette de taille préexistante (wiki_write.py/wiki_store.py vs guideline 300 l.) hors scope, sous le cap dur de 500.

🤖 Generated with Claude Code

…on all write paths

Issue #110: 8 call sites bypassed write_governed_page, so PR #109's
write-time frontmatter normalization only protected the interactive
wiki_write tool. Move normalize_frontmatter into wiki_store.write_page
itself (the true choke point every caller shares) so no path — governed
or direct — can persist a non-canonical frontmatter shape. Deduplicate
the now-redundant normalize call in write_governed_page, correct its
docstring's false "only function that may call write_page" claim, and
add an architecture test enumerating the audited whitelist of direct
callers so a new unreviewed bypass fails loudly instead of shipping
silently. Also fixes a regression introduced mid-change: routing
normalization through write_page's own try/except let
UnclosedFrontmatterError (a ValueError subclass) get silently
swallowed into an error dict instead of propagating.

Co-Authored-By: Claude <noreply@anthropic.com>
@cdeust
cdeust merged commit 45508bc into main Jul 14, 2026
14 checks passed
@cdeust
cdeust deleted the fix/wiki-write-path-governance branch July 14, 2026 09:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 write paths bypass write_governed_page — governance and write-time normalization not enforced

1 participant