Internal Documentation internal
TalkIDE internal documentation

Při startu nebo pokračování konverzace nad projektem BE automaticky injektuje OPEN PROJECT issues do CLAUDE.md — sekce # Open TODO issues. Mara tak vidí aktuální TODO list bez explicitního dotazu. UC nemá vlastní REST endpoint — jde o interní BE chování MaraContextRenderer.

  • Trigger: StartConversationUseCase, AutoStartConversationUseCase, SendMessageUseCase — kdekoliv se sestavuje CLAUDE.md pro danou konverzaci.
  • Řazení reported_at ASC, id ASC je kritické pro deterministické pořadí — Anthropic prompt cache hašuje obsah CLAUDE.md, nekonzistentní pořadí by invalidovalo cache a zvyšovalo náklady.
  • Limit 20 issues (N+1 trick): repository query používá LIMIT 21. Pokud výsledek vrátí 21 záznamů → je více než 20 → renderuj prvních 20 + summary řádek > _and more than 20 more open issues_. Přesné číslo se nevypisuje — žádný COUNT(*) query.
  • Empty case: pokud nejsou žádné OPEN/IN_PROGRESS issues, sekce # Open TODO issues se do CLAUDE.md nepřidá vůbec (prázdná sekce by zbytečně šumela prompt).
  • Pouze OPEN a IN_PROGRESS statusy jsou injektovány — TRIAGED, RESOLVED, WONTFIX, DUPLICATE se nezobrazují.

Flow — sestavení CLAUDE.md při startu konverzace

sequenceDiagram
    participant UC as StartConversationUseCase
    participant Renderer as MaraContextRenderer
    participant Repo as IssueRepository
    participant DB

    UC->>+Renderer: renderClaudeMd(projectId, tenantId, ...)

    Renderer->>+Repo: findByProjectIdAndStatusInOrderByReportedAtAscIdAsc(projectId, [OPEN, IN_PROGRESS])
    Repo->>DB: SELECT * FROM issues WHERE project_id=? AND tenant_id=? AND status IN ('OPEN','IN_PROGRESS')<br/>ORDER BY reported_at ASC, id ASC LIMIT 21
    DB-->>Repo: issues[]
    Repo-->>-Renderer: issues[]

    alt issues je prázdný []
        Renderer->>Renderer: nepřidávej sekci # Open TODO issues
    else issues.size <= 20 (vrátil méně než 21)
        Renderer->>Renderer: renderuj sekci se všemi issues, žádný summary řádek
    else issues.size == 21 (víc než 20 — N+1 trick)
        Renderer->>Renderer: renderuj sekci s prvními 20 issues + summary řádek<br/>"and more than 20 more open issues"<br/>Žádný COUNT(*) — přesné číslo se nevypisuje
    end

    Renderer-->>-UC: claudeMd (string s injektovanou sekcí nebo bez ní)

    UC->>UC: odešle CLAUDE.md do konverzace jako system context

Renderovaná sekce v CLAUDE.md

Formát

# Open TODO issues

- [BUG] SQL query vrací duplicitní řádky při JOIN bez DISTINCT (#660f9511) — Metoda UserRepository.findActiveUsers() vrací duplicitní záznamy kvůli chybějícímu DISTINCT…
- [FEATURE] Exportní funkce pro CSV (#771a0022) — Uživatelé potřebují exportovat data do CSV formátu pro zpracování v Excelu.
- [BUG] Přihlašovací formulář nepřijímá speciální znaky (#882b1133) — Po zadání hesla se speciálními znaky (např. !@#$) formulář zobrazí prázdnou error me…

Pravidla formátování

PrvekPravidlo
Prefix[BUG] nebo [FEATURE] dle kind
TitleBeze změny, originální text
ID(#<prvních 8 znaků UUID>) — zkrácené pro čitelnost; např. (#660f9511)
DescriptionZa pomlčkou ; description zkrácena na 100 znaků (trim + přidání pokud delší)
Oddělovač (mezera, pomlčka em-dash, mezera)
Summary řádek> _and more than 20 more open issues_ na konci sekce pokud issues > 20 (N+1 trick — přesné číslo se nevypisuje, žádný COUNT(*))

Příklad — plná sekce (2 issues)

# Open TODO issues

- [BUG] SQL query vrací duplicitní řádky při JOIN bez DISTINCT (#660f9511) — Metoda UserRepository.findActiveUsers() vrací duplicitní záznamy kvůli chybějícímu DISTINCT v…
- [FEATURE] Exportní funkce pro CSV (#771a0022) — Uživatelé potřebují exportovat data do CSV formátu pro zpracování v Excelu. Priorita: střední.

Příklad — truncated sekce (víc než 20 issues)

# Open TODO issues

- [BUG] Issue 1 (#aaaaaaaa) — popis…
- [BUG] Issue 2 (#bbbbbbbb) — popis…
[… dalších 18 issues …]
- [FEATURE] Issue 20 (#tttttttt) — popis…

> _and more than 20 more open issues_

Příklad — empty case (žádné OPEN/IN_PROGRESS issues)

CLAUDE.md sekce # Open TODO issues chybí úplně — žádný placeholder, žádný prázdný nadpis.


Implementační detail

Dotaz

// IssueRepository
fun findByProjectIdAndStatusInOrderByReportedAtAscIdAsc(
    projectId: UUID,
    statuses: List<IssueStatus>
): List<Issue>

SQL ekvivalent:

SELECT * FROM issues
WHERE project_id = :projectId
  AND tenant_id = :tenantId
  AND status IN ('OPEN', 'IN_PROGRESS')
ORDER BY reported_at ASC, id ASC
LIMIT 21

N+1 trick: BE fetchuje LIMIT 21. Pokud výsledek obsahuje 21 záznamů, víme že issues je více než 20 — renderuje prvních 20 + summary řádek > _and more than 20 more open issues_. Přesné číslo se nevypisuje, žádný separátní COUNT(*) query — cílem je minimalizovat load při každé Mara konverzaci.

Deterministické řazení pro prompt cache

Řazení reported_at ASC, id ASC:

  • reported_at ASC — nejstarší issues první (stabilní pořadí mezi requesty)
  • id ASC (UUID) — tiebreaker pro issues vytvořené ve stejnou sekundu (UUID je časově sekvenční z Hibernate UUIDGenerator)

Jakákoliv jiná řadící logika (random, reported_at DESC, bez tiebreakeru) by způsobovala nedeterministické pořadí → invalidaci Anthropic prompt cache → zbytečné náklady na tokenech.

Kde se volá MaraContextRenderer

UseCaseKdy se volá
StartConversationUseCaseNová konverzace nad projektem — CLAUDE.md se sestavuje od nuly
AutoStartConversationUseCaseAutomaticky spuštěná konverzace (batch operace) — stejné sestavení
SendMessageUseCasePokračování existující konverzace — CLAUDE.md se předává jako system context při každém volání

Renderer je stateless — pokaždé fetchuje aktuální stav issues z DB. Issues vyřešené mezi session spuštěním a dalším SendMessage se tedy projeví okamžitě v dalším volání (fresh fetch).


Backend

Test Cases

GIVENWHENTHEN
Projekt má 2 OPEN a 1 IN_PROGRESS issueMaraContextRenderer.renderClaudeMd(projectId, ...)CLAUDE.md obsahuje sekci # Open TODO issues se 3 záznamy, řazeno reported_at ASC, id ASC
Projekt nemá žádné OPEN ani IN_PROGRESS issuesMaraContextRenderer.renderClaudeMd(projectId, ...)CLAUDE.md neobsahuje sekci # Open TODO issues vůbec
Projekt má 25 OPEN issues (repository vrátí 21 řádků — N+1 trigger)MaraContextRenderer.renderClaudeMd(projectId, ...)CLAUDE.md obsahuje sekci s 20 záznamy + summary řádek > _and more than 20 more open issues_; žádný COUNT(*) query
Issue má description delší než 100 znakůMaraContextRenderer.renderClaudeMd(projectId, ...)Description je zkrácena na 100 znaků s
Projekt má RESOLVED a WONTFIX issues (žádné OPEN/IN_PROGRESS)MaraContextRenderer.renderClaudeMd(projectId, ...)Sekce # Open TODO issues chybí; RESOLVED/WONTFIX se nezobrazují
Dvě issues mají identické reported_atMaraContextRenderer.renderClaudeMd(projectId, ...)Pořadí je deterministické dle id ASC; opakované volání vrací stejné pořadí
Issues jsou ve stejném projektu, různé tenanty (cross-tenant data v DB)MaraContextRenderer.renderClaudeMd(projectId, tenantId)Vráceny pouze issues s tenant_id = tenantId; cross-tenant issues ignorovány

References


FEEDBACK

UC je netypický — nemá REST endpoint, jde o čistě interní BE chování. Dokumentační formát byl přizpůsoben (bez FE sekce, bez API contract bloku). Ambiguita summary řádku byla vyřešena: používá se N+1 trick (LIMIT 21), summary zní > _and more than 20 more open issues_ bez přesného čísla — žádný COUNT(*) query navíc. Cílem je minimalizovat DB load při každém SendMessage volání.


Was this page helpful?

Thanks for the feedback.