Skip to content

Retire le TTL des fiches (#8) et rend la KB lisible par un humain (#9) - #10

Merged
IamPhilG merged 4 commits into
mainfrom
claude/knowledge-base-ttl-format-2ugtgv
Aug 9, 2026
Merged

Retire le TTL des fiches (#8) et rend la KB lisible par un humain (#9)#10
IamPhilG merged 4 commits into
mainfrom
claude/knowledge-base-ttl-format-2ugtgv

Conversation

@IamPhilG

@IamPhilG IamPhilG commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Traite les deux issues ouvertes, dans l'ordre : d'abord le TTL, puis le format.

#8 — Durée de vie

ttl_days imposait une péremption automatique que rien n'appliquait : aucun outil ne le lisait, aucune revue ne s'en servait. Il donnait une fausse impression de fraîcheur pilotée.

  • clé retirée des 29 fiches active/**/*.json et des entrées d'index.json ;
  • KB-CONVENTIONS.md : champ retiré du schéma, règle de passage en suspect réécrite comme une décision de revue explicite — validated reste le marqueur de dernière vérification ;
  • deux fiches citaient ttl_days dans leur texte (codex-models, splunk-cim-data-models) : phrases reformulées sans changer le fond ;
  • kb.py validate rejette désormais le champ explicitement, pour qu'il ne revienne pas par copier-coller d'une ancienne fiche.

Zéro occurrence de ttl dans le repo après ce changement.

#9 — Format

Une fiche JSON dont tout le corps est une chaîne échappée est illisible sur GitHub, et une modification de contenu apparaît en PR comme une unique ligne de plusieurs milliers de caractères.

Deux arborescences commitées, une seule source de vérité. Le JSON sous active/ reste canonique : les repos consommateurs et le skill maxime-kb ne changent pas. md/, index.json et index.md sont dérivés et ne s'éditent jamais à la main.

active/<thème>/<id>.json source canonique, inchangée dans son rôle
md/active/<thème>/<id>.md miroir généré : frontmatter YAML + corps Markdown
index.json index machine, généré
index.md catalogue humain par thème, généré
tools/kb.py convertisseur bidirectionnel, Python 3 stdlib seule

Commandes : sync (JSON → Markdown), sync --from md (le « vice versa » de l'issue), check (vérifie sans écrire), validate.

L'aller-retour est sans perte, vérifié octet à octet sur les 29 fiches : reconstruire le JSON depuis le Markdown redonne exactement le JSON de départ. Le frontmatter est un sous-ensemble YAML restreint au schéma réel (scalaires texte et séquences de textes), ce qui permet de le parser sans dépendance tout en restant du YAML valide — GitHub l'affiche en tableau.

validate contrôle la présence et le type des 14 attributs, les valeurs contrôlées, id = nom de fichier, theme = dossier parent, le format des dates, l'unicité des id et la résolution des links.

Workflow kb-sync

Il ne se contente pas de vérifier : sur push, il régénère les index et le miroir et committe le résultat, pour qu'une modification de fiche n'oblige personne à lancer quoi que ce soit en local. Sur pull request depuis un fork, où pousser est impossible, il se rabat sur check en lecture seule.

Testé en conditions réelles sur une branche jetable : un commit modifiant un titre de fiche sans sync local a bien produit un commit github-actions[bot] mettant à jour exactement les 3 fichiers dérivés concernés, sans boucle de déclenchement.

Points à connaître avant de relire

  • index.json ne déclarait que 19 fiches sur 29. Les 10 autres étaient invisibles pour le skill, qui ne charge que ce que l'index déclare. Régénéré à 29 — c'est un correctif de fond, pas de la mise en forme.
  • index.md change de rôle : il devient un catalogue généré. Sa prose de conventions était redondante avec KB-CONVENTIONS.md et sa liste de thèmes périmée (elle citait coreapi, qui n'existe pas) ; elle a été fusionnée dans les conventions.
  • Les fiches JSON sont recanonicalisées (indentation 2, ordre des clés fixe, saut de ligne final) : 9 fiches sur 29 changent de mise en forme, sans aucun changement sémantique. C'est ce qui rend la comparaison de check déterministe.
  • Le gros du diff est constitué des 29 fichiers md/ générés — le code à relire tient dans tools/kb.py, .github/workflows/kb-sync.yml et KB-CONVENTIONS.md.
  • La branche tmp/kb-sync-selftest a servi au test du workflow et reste à supprimer : le proxy git de la session renvoie 403 sur les suppressions de branche.

Closes #8
Closes #9


Generated by Claude Code

claude added 3 commits August 9, 2026 09:44
Le champ imposait une péremption automatique que rien n'appliquait :
aucun outil ne le lisait, aucune revue ne s'en servait. Il donnait une
fausse impression de fraîcheur pilotée.

- clé ttl_days retirée des 29 fiches active/**/*.json et des entrées
  d'index.json
- KB-CONVENTIONS.md : champ retiré du schéma, règle de passage en
  `suspect` réécrite comme une décision de revue explicite, `validated`
  restant le marqueur de dernière vérification
- deux fiches citaient ttl_days dans leur contenu (codex-models,
  splunk-cim-data-models) : phrases reformulées sans changer le fond

Closes #8

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vh5PK8eE5U3PKNQ9tu8GxF
Une fiche JSON dont tout le corps est une chaîne échappée est illisible
sur GitHub, et un changement de contenu apparaît en PR comme une unique
ligne de plusieurs milliers de caractères. La KB gagne donc une
projection Markdown, sans cesser d'être consommée en JSON.

Le JSON sous active/ reste la source canonique : les repos consommateurs
et le skill maxime-kb ne changent pas. index.json, index.md et md/ sont
dérivés, jamais édités à la main.

- tools/kb.py : convertisseur bidirectionnel (sync, sync --from md,
  check, validate), Python 3 stdlib seule. Frontmatter YAML restreint au
  schéma réel, parsable sans dépendance ; aller-retour sans perte,
  vérifié octet à octet sur les 29 fiches.
- md/active/**.md : miroir généré, lisible et diffable.
- index.json régénéré : il ne déclarait que 19 fiches sur 29, les 10
  autres étaient invisibles pour le skill qui ne charge que l'index.
- index.md devient un catalogue généré par thème ; sa prose de
  conventions, redondante et périmée (thèmes obsolètes), rejoint
  KB-CONVENTIONS.md.
- fiches JSON recanonicalisées (indentation, ordre des clés, saut de
  ligne final) pour rendre la comparaison déterministe.
- .github/workflows/kb-sync.yml : régénère et committe les fichiers
  dérivés à chaque push ; se rabat sur une vérification en lecture seule
  pour les PR de fork.
- validate rejette explicitement ttl_days, pour que le champ retiré en
  #8 ne revienne pas par copier-coller.

Closes #9

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vh5PK8eE5U3PKNQ9tu8GxF

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca4e5e5301

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/kb.py
Comment on lines +437 to +439
for rel in md_paths():
if rel not in files:
(ROOT / rel).unlink()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Delete JSON orphans during Markdown-source sync

When sync --from md follows deletion or renaming of a Markdown fiche, the expected tree excludes the old fiche, but cleanup only traverses Markdown paths. The old canonical JSON therefore remains while the indexes are rewritten without it; the command exits successfully, the subsequent check fails, and a later default sync recreates the deleted Markdown fiche. Cleanup needs to remove orphaned JSON paths when Markdown is the selected source.

Useful? React with 👍 / 👎.

Comment thread tools/kb.py
else:
ids[fid] = rel
for rel, fiche in sorted(fiches.items()):
for link in fiche.get("links", []) or []:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Guard link traversal after recording a type error

When a malformed fiche supplies a truthy non-list value such as "links": 1, validate_fiche records the intended type error, but this loop immediately attempts to iterate the integer and raises an uncaught TypeError. Consequently validate, check, and sync emit a traceback instead of the actionable schema diagnostics; only traverse links after confirming the value is a list.

Useful? React with 👍 / 👎.

Comment thread tools/kb.py
# Une valeur doit être mise entre guillemets si elle est vide, porte une espace
# en tête/fin, contient un séparateur YAML (`: ` ou ` #`), ou commence par un
# caractère indicateur.
_NEEDS_QUOTES = re.compile(r"^$|^\s|\s$|:\s|\s#|^[-?:,\[\]{}#&*!|>'\"%@`]")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Quote multiline frontmatter scalars

A schema-valid string containing an internal newline, for example a multiline title or source, does not match this quoting expression unless whitespace also occurs at an endpoint. _dump_scalar consequently writes the newline directly into frontmatter, and the generated mirror cannot be parsed back (validate --from md reports the continuation as an unreadable line), violating the advertised lossless round trip. Quote values containing line breaks or other unsupported control characters.

Useful? React with 👍 / 👎.

index.json liste toutes les fiches, archivées comprises, pour qu'une
fiche archivée reste trouvable sur demande explicite. Mais c'est aussi
le seul fichier chargé systématiquement : si un consommateur ne filtre
pas, une fiche archivée peut être resservie comme connaissance
courante, et l'archivage devient cosmétique.

Le filtre repose sur `status`, donc `status` ne doit jamais pouvoir
diverger du dossier :

- validate refuse une fiche dans archived/ dont le statut n'est pas
  `archived` ;
- validate refuse une fiche marquée `archived` restée dans active/ —
  archiver, c'est la déplacer.
- KB-CONVENTIONS.md documente explicitement le contrat : le
  consommateur filtre sur `status` ou sur le préfixe `archived/` du
  champ `path`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vh5PK8eE5U3PKNQ9tu8GxF
@IamPhilG
IamPhilG merged commit d5678f2 into main Aug 9, 2026
4 checks passed
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.

Format Durée de vie

2 participants