Skip to content

Commit 79a76d2

Browse files
committed
Updated Mermaid diagrams across multiple documentation files to ensure proper syntax, including quoting labels and using consistent node IDs.
- Enhanced the architecture, configuration, deployment, and development documentation to improve readability and reduce parsing errors. - Introduced a normalization function in the documentation generation script to automate future Mermaid syntax corrections.
1 parent 3f3e1aa commit 79a76d2

36 files changed

Lines changed: 1138 additions & 89 deletions

File tree

mkdocs/docs/architecture.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ flowchart LR
6262
end
6363
6464
U -->|HTTP| A[FastAPI]
65-
A -->|async| V[VectorRetriever\nPostgres+pgvector]
66-
A -->|async| S[SparseRetriever\nPostgres FTS/BM25]
67-
A -->|async| G[GraphRetriever\nNeo4j]
65+
A -->|async| V["VectorRetriever\nPostgres+pgvector"]
66+
A -->|async| S["SparseRetriever\nPostgres FTS/BM25"]
67+
A -->|async| G["GraphRetriever\nNeo4j"]
6868
6969
V --> F[Fusion]
7070
S --> F
@@ -153,7 +153,7 @@ flowchart LR
153153

154154
```mermaid
155155
flowchart TB
156-
subgraph Tuning Inputs
156+
subgraph "Tuning Inputs"
157157
K[top_k]
158158
W[weights]
159159
RRF[rrf_k_div]

mkdocs/docs/architecture/health-metrics.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737

3838
```mermaid
3939
flowchart TB
40-
App --> /metrics
41-
/metrics --> Prom[Prometheus]
40+
App --> METRICS["/metrics"]
41+
METRICS["/metrics"] --> Prom[Prometheus]
4242
Postgres --> PExp[postgres-exporter]
4343
PExp --> Prom
4444
```

mkdocs/docs/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ flowchart LR
147147

148148
```mermaid
149149
flowchart TB
150-
U[User] --> UI[Frontend]\n(generated.ts)
150+
U[User] --> UI["Frontend\n(generated.ts)"]
151151
UI --> API[FastAPI /config]
152152
API --> P[Pydantic Models]
153153
P --> API

mkdocs/docs/deployment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ flowchart TB
9999
Pydantic --> Types[generated.ts]
100100
Types --> UI
101101
Compose --> API
102-
API --> /ready
102+
API --> READY["/ready"]
103103
```
104104

105105
??? note "Container Logs"

mkdocs/docs/dev/pydantic.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
```mermaid
4141
flowchart TB
42-
P[Pydantic\ntribrid_config_model.py] --> G[pydantic2ts\n(generate_types.py)]
42+
P["Pydantic\ntribrid_config_model.py"] --> G["pydantic2ts\n(generate_types.py)"]
4343
G --> T[generated.ts]
4444
T --> Z[Zustand Stores]
4545
Z --> H[Hooks]

mkdocs/docs/index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ TriBridRAG executes three independent retrieval methods in parallel and fuses th
6969

7070
```mermaid
7171
flowchart LR
72-
Q[Query] --> V[Vector Search\npgvector]
73-
Q --> S[Sparse Search\nPostgreSQL FTS/BM25]
74-
Q --> G[Graph Search\nNeo4j]
72+
Q[Query] --> V["Vector Search\npgvector"]
73+
Q --> S["Sparse Search\nPostgreSQL FTS/BM25"]
74+
Q --> G["Graph Search\nNeo4j"]
7575
V --> F[Fusion Layer]
7676
S --> F
7777
G --> F
@@ -197,7 +197,7 @@ Use ++ctrl+c++ to stop local uvicorn or Docker Tail sessions.
197197

198198
```mermaid
199199
flowchart TB
200-
CFG[Pydantic Config\nTriBridConfig] --> GEN[generate_types.py\nTypescript types]
200+
CFG["Pydantic Config\nTriBridConfig"] --> GEN["generate_types.py\nTypescript types"]
201201
GEN --> STO[Zustand Stores]
202202
STO --> HOOKS[React Hooks]
203203
HOOKS --> UI[Components]

scripts/docs_ai/docs_autopilot_enhanced.py

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22
"""
33
Enhanced Docs Autopilot for TriBridRAG
4-
Generates comprehensive documentation using OpenAI GPT-4 with full context awareness
4+
Generates comprehensive documentation using OpenAI GPT-5 (Responses API) with full context awareness
55
66
TriBridRAG is a tri-brid RAG engine combining:
77
- Vector search (pgvector in PostgreSQL)
@@ -23,6 +23,91 @@
2323
from dataclasses import dataclass, field
2424

2525

26+
_MERMAID_FENCE_RE = re.compile(r"```mermaid\s*\n(?P<code>[\s\S]*?)\n```", re.MULTILINE)
27+
28+
29+
def _normalize_mermaid_v11_code(code: str) -> str:
30+
"""
31+
Normalize Mermaid flowchart syntax to reduce Mermaid v11 parse errors.
32+
33+
This is intentionally conservative and only fixes common, mechanical issues:
34+
- `\\n` line breaks must be inside quoted labels: `A[foo\\nbar]` -> `A[\"foo\\nbar\"]`
35+
- `A[foo]\\nbar` -> `A[\"foo\\nbar\"]`
36+
- Endpoint tokens like `/metrics` must NOT be node IDs: `--> /metrics` -> `--> METRICS[\"/metrics\"]`
37+
- `subgraph` titles with spaces should be quoted: `subgraph Foo Bar` -> `subgraph \"Foo Bar\"`
38+
"""
39+
40+
fixed = code
41+
42+
# 1) Quote subgraph titles that contain spaces and are not already quoted / bracketed.
43+
lines: list[str] = []
44+
for line in fixed.splitlines():
45+
m = re.match(r"^(\s*)subgraph\s+([^\[\"\n]+)$", line)
46+
if m:
47+
indent, title = m.group(1), m.group(2).strip()
48+
if " " in title and not title.startswith('"') and "[" not in title:
49+
line = f'{indent}subgraph "{title}"'
50+
lines.append(line)
51+
fixed = "\n".join(lines)
52+
53+
# 2) Replace bare endpoint tokens used as node IDs.
54+
endpoint_nodes = {
55+
"/metrics": "METRICS",
56+
"/ready": "READY",
57+
"/health": "HEALTH",
58+
}
59+
for endpoint, node_id in endpoint_nodes.items():
60+
# ... --> /metrics
61+
fixed = re.sub(
62+
rf"(-->)\s*{re.escape(endpoint)}\s*$",
63+
rf'\1 {node_id}["{endpoint}"]',
64+
fixed,
65+
flags=re.MULTILINE,
66+
)
67+
# /metrics --> ...
68+
fixed = re.sub(
69+
rf"^(\s*){re.escape(endpoint)}(\s*-->)",
70+
rf'\1{node_id}["{endpoint}"]\2',
71+
fixed,
72+
flags=re.MULTILINE,
73+
)
74+
75+
# 3) Quote labels that contain a literal "\\n" inside brackets.
76+
# A[foo\nbar] -> A["foo\nbar"]
77+
fixed = re.sub(
78+
r'(\b[A-Za-z][A-Za-z0-9_]*)\[(?!")(\s*[^\]]*\\n[^\]]*)\]',
79+
r'\1["\2"]',
80+
fixed,
81+
)
82+
83+
# 4) Merge the invalid pattern: A[foo]\\nbar -> A["foo\\nbar"]
84+
fixed = re.sub(
85+
r'(\b[A-Za-z][A-Za-z0-9_]*)\[([^\]]+)\]\\n([^\n]+)$',
86+
r'\1["\2\\n\3"]',
87+
fixed,
88+
flags=re.MULTILINE,
89+
)
90+
91+
return fixed
92+
93+
94+
def normalize_mermaid_v11_markdown(markdown: str) -> Tuple[str, int]:
95+
"""Normalize Mermaid blocks in markdown. Returns (updated_markdown, blocks_changed)."""
96+
97+
blocks_changed = 0
98+
99+
def _replace(match: re.Match[str]) -> str:
100+
nonlocal blocks_changed
101+
code = match.group("code")
102+
normalized = _normalize_mermaid_v11_code(code)
103+
if normalized != code:
104+
blocks_changed += 1
105+
return f"```mermaid\n{normalized}\n```"
106+
107+
updated = _MERMAID_FENCE_RE.sub(_replace, markdown or "")
108+
return updated, blocks_changed
109+
110+
26111
@dataclass
27112
class DocumentationContext:
28113
"""Comprehensive context for documentation generation
@@ -504,6 +589,22 @@ def search(query: str, repo_id: str): # (1)
504589
Rerank --> Results[Final Results]
505590
```
506591
592+
### MERMAID v11 (CRITICAL: AVOID SYNTAX ERRORS)
593+
- ONLY generate `flowchart` diagrams (`flowchart LR` / `flowchart TB`). Avoid other diagram types.
594+
- NO HTML anywhere in Mermaid (no `<br>`, no tags, no raw HTML labels).
595+
- Node IDs MUST be simple: start with a letter, then letters/numbers/underscore only (`^[A-Za-z][A-Za-z0-9_]*$`).
596+
- NEVER use URL-ish or path-ish tokens as node IDs (e.g., do NOT write `--> /metrics`). Use an ID + quoted label:
597+
- `METRICS["/metrics"]`, `READY["/ready"]`, `HEALTH["/health"]`
598+
- If you want multi-line labels, you MUST quote the label and put `\\n` *inside* the quotes:
599+
- GOOD: `UI["Frontend\\n(generated.ts)"]`
600+
- BAD: `UI[Frontend]\\n(generated.ts)`
601+
- If you use `subgraph` and the title contains spaces, quote it:
602+
- GOOD: `subgraph "Tuning Inputs"`
603+
- GOOD: `subgraph tuning_inputs["Tuning Inputs"]`
604+
- BAD: `subgraph Tuning Inputs`
605+
- Prefer quoting any label containing punctuation like `/`, `(`, `)`, `:`, `+`, `-`.
606+
- Keep diagrams small and shallow. Prefer 6–14 nodes per diagram; use multiple diagrams instead of one huge diagram.
607+
507608
### 7. CONTENT ORGANIZATION
508609
- Use hierarchical headers (##, ###, ####)
509610
- Add table of contents markers
@@ -1126,10 +1227,38 @@ def write_documentation_files(self, docs_updates: Dict[str, str]) -> None:
11261227
# Filter content one more time before writing
11271228
filtered_content = self._filter_sensitive_content(content)
11281229
filtered_content = self._filter_banned_terms(filtered_content)
1230+
filtered_content, blocks_changed = normalize_mermaid_v11_markdown(filtered_content)
11291231

11301232
full_path.write_text(filtered_content, encoding="utf-8")
1233+
if blocks_changed:
1234+
print(f" ↳ Mermaid normalized: {blocks_changed} block(s)")
11311235
print(f" ✅ Wrote: {file_path}")
11321236

1237+
def normalize_existing_mermaid(self) -> Tuple[int, int]:
1238+
"""Normalize Mermaid blocks across existing mkdocs/docs markdown files."""
1239+
1240+
if not self.docs_dir.exists():
1241+
return 0, 0
1242+
1243+
files_changed = 0
1244+
blocks_changed_total = 0
1245+
1246+
for md_file in sorted(self.docs_dir.rglob("*.md")):
1247+
try:
1248+
original = md_file.read_text(encoding="utf-8")
1249+
except Exception:
1250+
continue
1251+
1252+
updated, blocks_changed = normalize_mermaid_v11_markdown(original)
1253+
if blocks_changed and updated != original:
1254+
md_file.write_text(updated, encoding="utf-8")
1255+
files_changed += 1
1256+
blocks_changed_total += blocks_changed
1257+
rel = md_file.relative_to(self.docs_dir)
1258+
print(f" ✅ Mermaid normalized: {rel} ({blocks_changed} block(s))")
1259+
1260+
return files_changed, blocks_changed_total
1261+
11331262
def write_mkdocs_config(self, config: dict) -> None:
11341263
"""Write mkdocs.yml configuration"""
11351264

@@ -1316,6 +1445,11 @@ def main():
13161445
parser.add_argument("--dry-run", action="store_true", help="Don't write files, just show what would be done")
13171446
parser.add_argument("--regenerate-all", action="store_true", help="Regenerate all documentation from entire codebase")
13181447
parser.add_argument("--full-scan", action="store_true", help="Scan entire repository, not just changes")
1448+
parser.add_argument(
1449+
"--normalize-mermaid",
1450+
action="store_true",
1451+
help="Normalize Mermaid v11 blocks in existing docs (no LLM call)",
1452+
)
13191453
args = parser.parse_args()
13201454

13211455
print("=" * 60)
@@ -1324,6 +1458,12 @@ def main():
13241458

13251459
autopilot = EnhancedDocsAutopilot()
13261460

1461+
if args.normalize_mermaid:
1462+
print("\n🧹 Normalizing Mermaid blocks across mkdocs/docs ...")
1463+
files_changed, blocks_changed = autopilot.normalize_existing_mermaid()
1464+
print(f"✅ Mermaid normalization complete: {files_changed} file(s), {blocks_changed} block(s) updated")
1465+
return
1466+
13271467
# Force full repository scan if regenerate-all or full-scan
13281468
if args.regenerate_all or args.full_scan:
13291469
print("\n🔄 Full repository scan mode - generating docs from entire codebase...")

scripts/generate_types.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,12 @@ def main() -> None:
225225
output_path = project_root / "web" / "src" / "types" / "generated.ts"
226226
output_path.parent.mkdir(parents=True, exist_ok=True)
227227

228-
print(f"\nSource: server.models.tribrid_config_model")
228+
print("\nSource: server.models.tribrid_config_model")
229229
print(f"Output: {output_path}\n")
230230

231231
try:
232232
# Import all models from THE LAW
233-
from server.models.tribrid_config_model import (
233+
from server.models.tribrid_config_model import ( # noqa: I001
234234
# Root config
235235
TriBridConfig,
236236
# Domain models - Index
@@ -245,6 +245,9 @@ def main() -> None:
245245
DashboardIndexStatusMetadata,
246246
DashboardIndexStatusResponse,
247247
DashboardIndexStatsResponse,
248+
# Domain models - Dev stack orchestration (local dev only)
249+
DevStackStatusResponse,
250+
DevStackRestartResponse,
248251
# Domain models - Corpora
249252
Corpus,
250253
CorpusCreateRequest,
@@ -308,6 +311,8 @@ def main() -> None:
308311
DashboardIndexStatusMetadata,
309312
DashboardIndexStatusResponse,
310313
DashboardIndexStatsResponse,
314+
DevStackStatusResponse,
315+
DevStackRestartResponse,
311316
Corpus,
312317
CorpusCreateRequest,
313318
CorpusUpdateRequest,

0 commit comments

Comments
 (0)