| """Wiki linter — health-checks the knowledge base for issues.""" |
|
|
| import anthropic |
| import json |
|
|
| LINT_SYSTEM_PROMPT = """You are auditing a nursing knowledge wiki for the Nursing Citizen Development Organisation. |
| Perform a thorough health check and identify: |
| |
| 1. **Contradictions**: Where articles disagree with each other or with current evidence |
| 2. **Stale content**: Claims that may be outdated (check against NMC 2018, NICE, NHS guidelines) |
| 3. **Orphan articles**: Articles with few or no backlinks (disconnected from the rest of the wiki) |
| 4. **Missing cross-references**: Where articles should link to each other but don't |
| 5. **Clinical safety gaps**: Important safety information that is absent or incomplete |
| 6. **Missing articles**: Important nursing topics not yet covered (suggest 3-5 new articles) |
| 7. **Evidence gaps**: Claims without adequate citation |
| |
| Return a structured JSON report: |
| { |
| "overall_health": "Good/Fair/Needs attention", |
| "total_issues": number, |
| "issues": [ |
| { |
| "type": "contradiction|stale|orphan|missing_link|safety_gap|evidence_gap", |
| "severity": "high|medium|low", |
| "article": "article_slug or 'wiki-wide'", |
| "description": "Clear description of the issue", |
| "recommendation": "Specific action to fix it" |
| } |
| ], |
| "suggested_new_articles": [ |
| { |
| "title": "Suggested Article Title", |
| "category": "category", |
| "rationale": "Why this article is needed", |
| "key_topics": ["topic1", "topic2"] |
| } |
| ], |
| "strengths": ["What the wiki does well"], |
| "summary": "Brief overall assessment" |
| } |
| """ |
|
|
|
|
| def lint_wiki(client: anthropic.Anthropic, articles: dict, index_summary: str, |
| model: str = "claude-sonnet-4-6") -> dict: |
| """ |
| Run a health check on the wiki. |
| |
| Returns a structured report with issues and recommendations. |
| """ |
| |
| article_summaries = [] |
| for slug, art in articles.items(): |
| |
| import re |
| backlinks = re.findall(r'\[\[([^\]]+)\]\]', art["content"]) |
| article_summaries.append({ |
| "slug": slug, |
| "title": art["title"], |
| "category": art["category"], |
| "tags": art.get("tags", []), |
| "last_updated": art.get("last_updated", "unknown"), |
| "word_count": len(art["content"].split()), |
| "backlinks": backlinks, |
| "sources": art.get("sources", []), |
| "content_preview": art["content"][:600], |
| }) |
|
|
| prompt = f"""## Wiki Index |
| {index_summary} |
| |
| ## Article Summaries |
| {json.dumps(article_summaries, indent=2)[:12000]} |
| |
| Please perform a thorough health check of this nursing knowledge wiki. |
| Return valid JSON only, no markdown fences.""" |
|
|
| response = client.messages.create( |
| model=model, |
| max_tokens=3000, |
| system=LINT_SYSTEM_PROMPT, |
| messages=[{"role": "user", "content": prompt}], |
| ) |
|
|
| raw = response.content[0].text.strip() |
| if raw.startswith("```"): |
| raw = raw.split("\n", 1)[1] |
| if raw.endswith("```"): |
| raw = raw.rsplit("```", 1)[0] |
|
|
| return json.loads(raw) |
|
|
|
|
| def generate_missing_article(client: anthropic.Anthropic, title: str, category: str, |
| key_topics: list, existing_index: str, |
| model: str = "claude-sonnet-4-6") -> dict: |
| """Generate a new article for a topic identified as missing by the linter.""" |
| import datetime |
|
|
| prompt = f"""Write a comprehensive nursing knowledge wiki article on: **{title}** |
| |
| Category: {category} |
| Key topics to cover: {', '.join(key_topics)} |
| |
| Existing wiki context (do not duplicate, but do cross-reference): |
| {existing_index} |
| |
| The article should: |
| - Be clinically accurate and evidence-based (NMC 2018, NICE, NHS, BNF standards) |
| - Use UK spellings and references |
| - Include backlinks to related articles using [[Article Title]] format |
| - Have clear sections with ## headers |
| - Include a References section |
| - Be suitable for student nurses |
| |
| Return the full markdown article content only (no JSON, just the markdown).""" |
|
|
| response = client.messages.create( |
| model=model, |
| max_tokens=3000, |
| messages=[{"role": "user", "content": prompt}], |
| ) |
|
|
| content = response.content[0].text.strip() |
| slug = title.lower().replace(" ", "_").replace("-", "_") |
| slug = "".join(c for c in slug if c.isalnum() or c == "_") |
|
|
| return { |
| "slug": slug, |
| "title": title, |
| "category": category, |
| "tags": key_topics[:5], |
| "content": content, |
| "last_updated": datetime.date.today().isoformat(), |
| "sources": ["AI-generated from lint suggestion"], |
| } |
|
|