You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
The code-graphs cache grows without bound and is never pruned when a worktree is removed #711
~/.cache/cortex/code-graphs grows without bound. Every project or worktree where a session opens gets its own code graph of 0.6 to 1.1 GB, and nothing removes it when the worktree is deleted. A machine used with many worktrees accumulates tens of gigabytes.
Evidence
Measured on 2026-10-10 on a development machine that runs many short-lived worktrees.
mcp_server/handlers/ingest_codebase.py line 108 builds the location as ~/.cache/cortex/code-graphs/<project key> and the SessionStart hook ingests the current project in a detached background process.
The directory held 60 entries and 12 GB. Entries are named after worktrees (for example fix-665-windows-registry-44d852f6) with 0.6 to 1.1 GB each. Nine of them recorded a project root (in meta.json) that no longer existed, 3.4 GB; 43 had no meta.json at all (5.2 GB), so they cannot be tied to a root or cleaned safely.
A graph directory always carries a meta.json with its root; a cache is removed when its root no longer exists (a cleanup at SessionStart and when a worktree is removed), the total size is bounded with an eviction rule that never touches a graph in use, and a worktree session does not rebuild a full graph when the parent project's graph is current (share it, or ingest incrementally). A test that deletes a root and expects its graph to be pruned, and one that a directory without meta.json is reported, not silently kept.
First slice opened: #869 (Refs #711, does not close the issue).
Cause: nothing tied a graph directory to its project. The only cleanup matched siblings by name prefix. So it never removed the graph of a deleted worktree, and it deleted unrelated projects (cortex-viz-* when cortex was ingested).
Remaining slices: (2) a size cap with an eviction that never touches a graph in use; (3) pruning when a worktree is removed; (4) a worktree reuses the parent's graph or ingests it incrementally.
Open question for the owner: the ~43 existing directories with no marker. Tying them to a root would mean reading AP's meta.json, whose schema is not defined in this repository.
Second slice opened: #897 (Refs #711, does not close the issue).
Cause: slice 1 pruned orphaned graphs only at the end of a successful ingest_codebase. A session with a fresh graph, no pipeline or a failed analyze never pruned.
Remaining slices: (3) a size cap with an eviction that never touches a graph in use (needs a sourced cap value: owner decision); (4) pruning when a worktree is removed; (5) a worktree reuses the parent's graph or ingests incrementally.
Not verified: the hook's added latency on a real ~60-entry cache, and the CI mutation gate.
Passage autopilot : aucune tranche restante n'est livrable sans décision du propriétaire, je pose autopilot:hold.
Tranche 3 (plafond de taille + éviction) : aucune valeur de plafond n'est sourcée dans le dépôt (règle « No source, no implementation »). À trancher : le plafond (en Go, ou en nombre de graphes) et la règle d'éviction (LRU sur la date d'accès ? jamais un graphe dont le cortex-root.json nomme un répertoire existant ?).
Tranche 4 (élagage à la suppression d'un worktree) : depuis fix(hooks): SessionStart prunes orphaned code graphs even when it ingests nothing (#711, slice 2) #897, le SessionStart suivant supprime déjà le graphe d'un worktree disparu. Un élagage au moment de la suppression demande une source d'événement : git n'a pas de hook post-worktree remove, et le dépôt ne référence aucun événement de suppression de worktree côté hôte. À trancher : le SessionStart suffit-il (fermer cette tranche), ou faut-il brancher un événement hôte précis (lequel) ?
Tranche 5 (worktree réutilisant le graphe du parent) : choix de conception entre partager le graphe du projet parent (lecture seule, risque de résultats périmés pour les fichiers modifiés dans le worktree) et une ingestion incrémentale depuis le graphe parent. À trancher : lequel.
Décision : cette issue n'attend plus de réponse du propriétaire.
Le propriétaire a demandé le 12 novembre 2026 que les issues avancent sans lui ; il ne répondra pas aux questions posées ici. Ce commentaire de cdeust lève le hold et précise la demande. Il vaut pour toute la suite de cette issue.
Tranche toi-même chaque question restée ouverte : d'abord une décision écrite et acceptée du dépôt (ADR accepté, docs/), puis ce que le texte de l'issue propose ou exclut, puis les standards du dépôt ; à défaut, la plus petite tranche qui réalise ce que l'issue demande. Une valeur qui manque se mesure, elle ne s'invente pas.
Écris la décision dans un commentaire marqué <!-- ci-autopilot decision --> (ce qui est retenu, la raison et sa source, ce qui est écarté, comment revenir en arrière), puis livre la tranche dans une PR. Une décision écrite ne se rejoue pas aux passages suivants.
Ne repose pas autopilot:hold pour une question : seulement pour l'irréversible, un accès que tu n'as pas, une dépendance nommée encore ouverte ou le plafond de tentatives, en nommant exactement ce qui manque.
Jamais de tag, de release, de montée de version du projet ni de déclenchement manuel d'un workflow.
Hold autopilot:hold levé : un commentaire de cdeust (« Décision : cette issue n'attend plus de réponse du propriétaire », 12/11/2026) a été posté après la pose du hold.
Activity
cdeust commentedon Nov 4, 2026
First slice opened: #869 (
Refs #711, does not close the issue).cortex-viz-*whencortexwas ingested).cortex-root.jsonnext to each graph it builds. It removes graphs whose root no longer exists. A directory with no marker is reported in the log and kept.meta.json, whose schema is not defined in this repository.Generated by Claude Code
fixup! fix(ingest): tie each code graph to its root and prune graphs …
fixup! fix(ingest): tie each code graph to its root and prune graphs …
fixup! fix(ingest): tie each code graph to its root and prune graphs …
Merge pull request #869 from cdeust/fix/711-code-graph-orphan-prune
cdeust commentedon Nov 5, 2026
Second slice opened: #897 (
Refs #711, does not close the issue).ingest_codebase. A session with a fresh graph, no pipeline or a failed analyze never pruned.cortex-root.jsonmarkers of~/.cache/cortex/code-graphsand, when one names a root that no longer exists, starts a detached worker (code_graph_prune_background) that removes it. Unmarked directories are still reported and kept.Generated by Claude Code
fixup! fix(hooks): SessionStart prunes orphaned code graphs even when…
fix(hooks): SessionStart prunes orphaned code graphs even when it ing…
fixup! fix(hooks): SessionStart prunes orphaned code graphs even when…
fixup! fix(hooks): SessionStart prunes orphaned code graphs even when…
Merge pull request #897 from cdeust/fix/711-session-start-graph-prune
cdeust commentedon Nov 6, 2026
Passage autopilot : aucune tranche restante n'est livrable sans décision du propriétaire, je pose
autopilot:hold.cortex-root.jsonnomme un répertoire existant ?).worktree remove, et le dépôt ne référence aucun événement de suppression de worktree côté hôte. À trancher : le SessionStart suffit-il (fermer cette tranche), ou faut-il brancher un événement hôte précis (lequel) ?Generated by Claude Code
cdeust commentedon Nov 12, 2026
Décision : cette issue n'attend plus de réponse du propriétaire.
Le propriétaire a demandé le 12 novembre 2026 que les issues avancent sans lui ; il ne répondra pas aux questions posées ici. Ce commentaire de
cdeustlève le hold et précise la demande. Il vaut pour toute la suite de cette issue.docs/), puis ce que le texte de l'issue propose ou exclut, puis les standards du dépôt ; à défaut, la plus petite tranche qui réalise ce que l'issue demande. Une valeur qui manque se mesure, elle ne s'invente pas.<!-- ci-autopilot decision -->(ce qui est retenu, la raison et sa source, ce qui est écarté, comment revenir en arrière), puis livre la tranche dans une PR. Une décision écrite ne se rejoue pas aux passages suivants.autopilot:holdpour une question : seulement pour l'irréversible, un accès que tu n'as pas, une dépendance nommée encore ouverte ou le plafond de tentatives, en nommant exactement ce qui manque.Règle complète : #343 (comment)
Écrit par la session « écosystème autonome » sur instruction du propriétaire (12 novembre 2026).
Generated by Claude Code
cdeust commentedon Nov 12, 2026
Hold
autopilot:holdlevé : un commentaire decdeust(« Décision : cette issue n'attend plus de réponse du propriétaire », 12/11/2026) a été posté après la pose du hold.Generated by Claude Code