@booklib/core 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/booklib-standards.mdc +40 -0
- package/.gemini/context.md +372 -0
- package/AGENTS.md +166 -0
- package/CHANGELOG.md +226 -0
- package/CLAUDE.md +81 -0
- package/CODE_OF_CONDUCT.md +31 -0
- package/CONTRIBUTING.md +304 -0
- package/LICENSE +21 -0
- package/PLAN.md +28 -0
- package/README.ja.md +198 -0
- package/README.ko.md +198 -0
- package/README.md +503 -0
- package/README.pt-BR.md +198 -0
- package/README.uk.md +241 -0
- package/README.zh-CN.md +198 -0
- package/SECURITY.md +9 -0
- package/agents/architecture-reviewer.md +136 -0
- package/agents/booklib-reviewer.md +90 -0
- package/agents/data-reviewer.md +107 -0
- package/agents/jvm-reviewer.md +146 -0
- package/agents/python-reviewer.md +128 -0
- package/agents/rust-reviewer.md +115 -0
- package/agents/ts-reviewer.md +110 -0
- package/agents/ui-reviewer.md +117 -0
- package/assets/logo.svg +36 -0
- package/bin/booklib-mcp.js +304 -0
- package/bin/booklib.js +1705 -0
- package/bin/skills.cjs +1292 -0
- package/booklib-router.mdc +36 -0
- package/booklib.config.json +19 -0
- package/commands/animation-at-work.md +10 -0
- package/commands/clean-code-reviewer.md +10 -0
- package/commands/data-intensive-patterns.md +10 -0
- package/commands/data-pipelines.md +10 -0
- package/commands/design-patterns.md +10 -0
- package/commands/domain-driven-design.md +10 -0
- package/commands/effective-java.md +10 -0
- package/commands/effective-kotlin.md +10 -0
- package/commands/effective-python.md +10 -0
- package/commands/effective-typescript.md +10 -0
- package/commands/kotlin-in-action.md +10 -0
- package/commands/lean-startup.md +10 -0
- package/commands/microservices-patterns.md +10 -0
- package/commands/programming-with-rust.md +10 -0
- package/commands/refactoring-ui.md +10 -0
- package/commands/rust-in-action.md +10 -0
- package/commands/skill-router.md +10 -0
- package/commands/spring-boot-in-action.md +10 -0
- package/commands/storytelling-with-data.md +10 -0
- package/commands/system-design-interview.md +10 -0
- package/commands/using-asyncio-python.md +10 -0
- package/commands/web-scraping-python.md +10 -0
- package/community/registry.json +1616 -0
- package/hooks/hooks.json +23 -0
- package/hooks/posttooluse-capture.mjs +67 -0
- package/hooks/suggest.js +153 -0
- package/lib/agent-behaviors.js +40 -0
- package/lib/agent-detector.js +96 -0
- package/lib/config-loader.js +39 -0
- package/lib/conflict-resolver.js +148 -0
- package/lib/context-builder.js +574 -0
- package/lib/discovery-engine.js +298 -0
- package/lib/doctor/hook-installer.js +83 -0
- package/lib/doctor/usage-tracker.js +87 -0
- package/lib/engine/ai-features.js +253 -0
- package/lib/engine/auditor.js +103 -0
- package/lib/engine/bm25-index.js +178 -0
- package/lib/engine/capture.js +120 -0
- package/lib/engine/corrections.js +198 -0
- package/lib/engine/doctor.js +195 -0
- package/lib/engine/graph-injector.js +137 -0
- package/lib/engine/graph.js +161 -0
- package/lib/engine/handoff.js +405 -0
- package/lib/engine/indexer.js +242 -0
- package/lib/engine/parser.js +53 -0
- package/lib/engine/query-expander.js +42 -0
- package/lib/engine/reranker.js +40 -0
- package/lib/engine/rrf.js +59 -0
- package/lib/engine/scanner.js +151 -0
- package/lib/engine/searcher.js +139 -0
- package/lib/engine/session-coordinator.js +306 -0
- package/lib/engine/session-manager.js +429 -0
- package/lib/engine/synthesizer.js +70 -0
- package/lib/installer.js +70 -0
- package/lib/instinct-block.js +33 -0
- package/lib/mcp-config-writer.js +88 -0
- package/lib/paths.js +57 -0
- package/lib/profiles/design.md +19 -0
- package/lib/profiles/general.md +16 -0
- package/lib/profiles/research-analysis.md +22 -0
- package/lib/profiles/software-development.md +23 -0
- package/lib/profiles/writing-content.md +19 -0
- package/lib/project-initializer.js +916 -0
- package/lib/registry/skills.js +102 -0
- package/lib/registry-searcher.js +99 -0
- package/lib/rules/rules-manager.js +169 -0
- package/lib/skill-fetcher.js +333 -0
- package/lib/well-known-builder.js +70 -0
- package/lib/wizard/index.js +404 -0
- package/lib/wizard/integration-detector.js +41 -0
- package/lib/wizard/project-detector.js +100 -0
- package/lib/wizard/prompt.js +156 -0
- package/lib/wizard/registry-embeddings.js +107 -0
- package/lib/wizard/skill-recommender.js +69 -0
- package/llms-full.txt +254 -0
- package/llms.txt +70 -0
- package/package.json +45 -0
- package/research-reports/2026-04-01-current-architecture.md +160 -0
- package/research-reports/IDEAS.md +93 -0
- package/rules/common/clean-code.md +42 -0
- package/rules/java/effective-java.md +42 -0
- package/rules/kotlin/effective-kotlin.md +37 -0
- package/rules/python/effective-python.md +38 -0
- package/rules/rust/rust.md +37 -0
- package/rules/typescript/effective-typescript.md +42 -0
- package/scripts/gen-llms-full.mjs +36 -0
- package/scripts/gen-og.mjs +142 -0
- package/scripts/validate-frontmatter.js +25 -0
- package/skills/animation-at-work/SKILL.md +270 -0
- package/skills/animation-at-work/assets/example_asset.txt +1 -0
- package/skills/animation-at-work/evals/evals.json +44 -0
- package/skills/animation-at-work/evals/results.json +13 -0
- package/skills/animation-at-work/examples/after.md +64 -0
- package/skills/animation-at-work/examples/before.md +35 -0
- package/skills/animation-at-work/references/api_reference.md +369 -0
- package/skills/animation-at-work/references/review-checklist.md +79 -0
- package/skills/animation-at-work/scripts/audit_animations.py +295 -0
- package/skills/animation-at-work/scripts/example.py +1 -0
- package/skills/clean-code-reviewer/SKILL.md +444 -0
- package/skills/clean-code-reviewer/audit.json +35 -0
- package/skills/clean-code-reviewer/evals/evals.json +185 -0
- package/skills/clean-code-reviewer/evals/results.json +13 -0
- package/skills/clean-code-reviewer/examples/after.md +48 -0
- package/skills/clean-code-reviewer/examples/before.md +33 -0
- package/skills/clean-code-reviewer/references/api_reference.md +158 -0
- package/skills/clean-code-reviewer/references/practices-catalog.md +282 -0
- package/skills/clean-code-reviewer/references/review-checklist.md +254 -0
- package/skills/clean-code-reviewer/scripts/pre-review.py +206 -0
- package/skills/data-intensive-patterns/SKILL.md +267 -0
- package/skills/data-intensive-patterns/assets/example_asset.txt +1 -0
- package/skills/data-intensive-patterns/evals/evals.json +54 -0
- package/skills/data-intensive-patterns/evals/results.json +13 -0
- package/skills/data-intensive-patterns/examples/after.md +61 -0
- package/skills/data-intensive-patterns/examples/before.md +38 -0
- package/skills/data-intensive-patterns/references/api_reference.md +34 -0
- package/skills/data-intensive-patterns/references/patterns-catalog.md +551 -0
- package/skills/data-intensive-patterns/references/review-checklist.md +193 -0
- package/skills/data-intensive-patterns/scripts/adr.py +213 -0
- package/skills/data-intensive-patterns/scripts/example.py +1 -0
- package/skills/data-pipelines/SKILL.md +259 -0
- package/skills/data-pipelines/assets/example_asset.txt +1 -0
- package/skills/data-pipelines/evals/evals.json +45 -0
- package/skills/data-pipelines/evals/results.json +13 -0
- package/skills/data-pipelines/examples/after.md +97 -0
- package/skills/data-pipelines/examples/before.md +37 -0
- package/skills/data-pipelines/references/api_reference.md +301 -0
- package/skills/data-pipelines/references/review-checklist.md +181 -0
- package/skills/data-pipelines/scripts/example.py +1 -0
- package/skills/data-pipelines/scripts/new_pipeline.py +444 -0
- package/skills/design-patterns/SKILL.md +271 -0
- package/skills/design-patterns/assets/example_asset.txt +1 -0
- package/skills/design-patterns/evals/evals.json +46 -0
- package/skills/design-patterns/evals/results.json +13 -0
- package/skills/design-patterns/examples/after.md +52 -0
- package/skills/design-patterns/examples/before.md +29 -0
- package/skills/design-patterns/references/api_reference.md +1 -0
- package/skills/design-patterns/references/patterns-catalog.md +726 -0
- package/skills/design-patterns/references/review-checklist.md +173 -0
- package/skills/design-patterns/scripts/example.py +1 -0
- package/skills/design-patterns/scripts/scaffold.py +807 -0
- package/skills/domain-driven-design/SKILL.md +142 -0
- package/skills/domain-driven-design/assets/example_asset.txt +1 -0
- package/skills/domain-driven-design/evals/evals.json +48 -0
- package/skills/domain-driven-design/evals/results.json +13 -0
- package/skills/domain-driven-design/examples/after.md +80 -0
- package/skills/domain-driven-design/examples/before.md +43 -0
- package/skills/domain-driven-design/references/api_reference.md +1 -0
- package/skills/domain-driven-design/references/patterns-catalog.md +545 -0
- package/skills/domain-driven-design/references/review-checklist.md +158 -0
- package/skills/domain-driven-design/scripts/example.py +1 -0
- package/skills/domain-driven-design/scripts/scaffold.py +421 -0
- package/skills/effective-java/SKILL.md +227 -0
- package/skills/effective-java/assets/example_asset.txt +1 -0
- package/skills/effective-java/evals/evals.json +46 -0
- package/skills/effective-java/evals/results.json +13 -0
- package/skills/effective-java/examples/after.md +83 -0
- package/skills/effective-java/examples/before.md +37 -0
- package/skills/effective-java/references/api_reference.md +1 -0
- package/skills/effective-java/references/items-catalog.md +955 -0
- package/skills/effective-java/references/review-checklist.md +216 -0
- package/skills/effective-java/scripts/checkstyle_setup.py +211 -0
- package/skills/effective-java/scripts/example.py +1 -0
- package/skills/effective-kotlin/SKILL.md +271 -0
- package/skills/effective-kotlin/assets/example_asset.txt +1 -0
- package/skills/effective-kotlin/audit.json +29 -0
- package/skills/effective-kotlin/evals/evals.json +45 -0
- package/skills/effective-kotlin/evals/results.json +13 -0
- package/skills/effective-kotlin/examples/after.md +36 -0
- package/skills/effective-kotlin/examples/before.md +38 -0
- package/skills/effective-kotlin/references/api_reference.md +1 -0
- package/skills/effective-kotlin/references/practices-catalog.md +1228 -0
- package/skills/effective-kotlin/references/review-checklist.md +126 -0
- package/skills/effective-kotlin/scripts/example.py +1 -0
- package/skills/effective-python/SKILL.md +441 -0
- package/skills/effective-python/evals/evals.json +44 -0
- package/skills/effective-python/evals/results.json +13 -0
- package/skills/effective-python/examples/after.md +56 -0
- package/skills/effective-python/examples/before.md +40 -0
- package/skills/effective-python/ref-01-pythonic-thinking.md +202 -0
- package/skills/effective-python/ref-02-lists-and-dicts.md +146 -0
- package/skills/effective-python/ref-03-functions.md +186 -0
- package/skills/effective-python/ref-04-comprehensions-generators.md +211 -0
- package/skills/effective-python/ref-05-classes-interfaces.md +188 -0
- package/skills/effective-python/ref-06-metaclasses-attributes.md +209 -0
- package/skills/effective-python/ref-07-concurrency.md +213 -0
- package/skills/effective-python/ref-08-robustness-performance.md +248 -0
- package/skills/effective-python/ref-09-testing-debugging.md +253 -0
- package/skills/effective-python/ref-10-collaboration.md +175 -0
- package/skills/effective-python/references/api_reference.md +218 -0
- package/skills/effective-python/references/practices-catalog.md +483 -0
- package/skills/effective-python/references/review-checklist.md +190 -0
- package/skills/effective-python/scripts/lint.py +173 -0
- package/skills/effective-typescript/SKILL.md +262 -0
- package/skills/effective-typescript/audit.json +29 -0
- package/skills/effective-typescript/evals/evals.json +37 -0
- package/skills/effective-typescript/evals/results.json +13 -0
- package/skills/effective-typescript/examples/after.md +70 -0
- package/skills/effective-typescript/examples/before.md +47 -0
- package/skills/effective-typescript/references/api_reference.md +118 -0
- package/skills/effective-typescript/references/practices-catalog.md +371 -0
- package/skills/effective-typescript/scripts/review.py +169 -0
- package/skills/kotlin-in-action/SKILL.md +261 -0
- package/skills/kotlin-in-action/assets/example_asset.txt +1 -0
- package/skills/kotlin-in-action/evals/evals.json +43 -0
- package/skills/kotlin-in-action/evals/results.json +13 -0
- package/skills/kotlin-in-action/examples/after.md +53 -0
- package/skills/kotlin-in-action/examples/before.md +39 -0
- package/skills/kotlin-in-action/references/api_reference.md +1 -0
- package/skills/kotlin-in-action/references/practices-catalog.md +436 -0
- package/skills/kotlin-in-action/references/review-checklist.md +204 -0
- package/skills/kotlin-in-action/scripts/example.py +1 -0
- package/skills/kotlin-in-action/scripts/setup_detekt.py +224 -0
- package/skills/lean-startup/SKILL.md +160 -0
- package/skills/lean-startup/assets/example_asset.txt +1 -0
- package/skills/lean-startup/evals/evals.json +43 -0
- package/skills/lean-startup/evals/results.json +13 -0
- package/skills/lean-startup/examples/after.md +80 -0
- package/skills/lean-startup/examples/before.md +34 -0
- package/skills/lean-startup/references/api_reference.md +319 -0
- package/skills/lean-startup/references/review-checklist.md +137 -0
- package/skills/lean-startup/scripts/example.py +1 -0
- package/skills/lean-startup/scripts/new_experiment.py +286 -0
- package/skills/microservices-patterns/SKILL.md +384 -0
- package/skills/microservices-patterns/evals/evals.json +45 -0
- package/skills/microservices-patterns/evals/results.json +13 -0
- package/skills/microservices-patterns/examples/after.md +69 -0
- package/skills/microservices-patterns/examples/before.md +40 -0
- package/skills/microservices-patterns/references/patterns-catalog.md +391 -0
- package/skills/microservices-patterns/references/review-checklist.md +169 -0
- package/skills/microservices-patterns/scripts/new_service.py +583 -0
- package/skills/programming-with-rust/SKILL.md +209 -0
- package/skills/programming-with-rust/evals/evals.json +37 -0
- package/skills/programming-with-rust/evals/results.json +13 -0
- package/skills/programming-with-rust/examples/after.md +107 -0
- package/skills/programming-with-rust/examples/before.md +59 -0
- package/skills/programming-with-rust/references/api_reference.md +152 -0
- package/skills/programming-with-rust/references/practices-catalog.md +335 -0
- package/skills/programming-with-rust/scripts/review.py +142 -0
- package/skills/refactoring-ui/SKILL.md +362 -0
- package/skills/refactoring-ui/assets/example_asset.txt +1 -0
- package/skills/refactoring-ui/evals/evals.json +45 -0
- package/skills/refactoring-ui/evals/results.json +13 -0
- package/skills/refactoring-ui/examples/after.md +85 -0
- package/skills/refactoring-ui/examples/before.md +58 -0
- package/skills/refactoring-ui/references/api_reference.md +355 -0
- package/skills/refactoring-ui/references/review-checklist.md +114 -0
- package/skills/refactoring-ui/scripts/audit_css.py +250 -0
- package/skills/refactoring-ui/scripts/example.py +1 -0
- package/skills/rust-in-action/SKILL.md +350 -0
- package/skills/rust-in-action/evals/evals.json +38 -0
- package/skills/rust-in-action/evals/results.json +13 -0
- package/skills/rust-in-action/examples/after.md +156 -0
- package/skills/rust-in-action/examples/before.md +56 -0
- package/skills/rust-in-action/references/practices-catalog.md +346 -0
- package/skills/rust-in-action/scripts/review.py +147 -0
- package/skills/skill-router/SKILL.md +186 -0
- package/skills/skill-router/evals/evals.json +38 -0
- package/skills/skill-router/evals/results.json +13 -0
- package/skills/skill-router/examples/after.md +63 -0
- package/skills/skill-router/examples/before.md +39 -0
- package/skills/skill-router/references/api_reference.md +24 -0
- package/skills/skill-router/references/routing-heuristics.md +89 -0
- package/skills/skill-router/references/skill-catalog.md +174 -0
- package/skills/skill-router/scripts/route.py +266 -0
- package/skills/spring-boot-in-action/SKILL.md +340 -0
- package/skills/spring-boot-in-action/evals/evals.json +39 -0
- package/skills/spring-boot-in-action/evals/results.json +13 -0
- package/skills/spring-boot-in-action/examples/after.md +185 -0
- package/skills/spring-boot-in-action/examples/before.md +84 -0
- package/skills/spring-boot-in-action/references/practices-catalog.md +403 -0
- package/skills/spring-boot-in-action/scripts/review.py +184 -0
- package/skills/storytelling-with-data/SKILL.md +241 -0
- package/skills/storytelling-with-data/assets/example_asset.txt +1 -0
- package/skills/storytelling-with-data/evals/evals.json +47 -0
- package/skills/storytelling-with-data/evals/results.json +13 -0
- package/skills/storytelling-with-data/examples/after.md +50 -0
- package/skills/storytelling-with-data/examples/before.md +33 -0
- package/skills/storytelling-with-data/references/api_reference.md +379 -0
- package/skills/storytelling-with-data/references/review-checklist.md +111 -0
- package/skills/storytelling-with-data/scripts/chart_review.py +301 -0
- package/skills/storytelling-with-data/scripts/example.py +1 -0
- package/skills/system-design-interview/SKILL.md +233 -0
- package/skills/system-design-interview/assets/example_asset.txt +1 -0
- package/skills/system-design-interview/evals/evals.json +46 -0
- package/skills/system-design-interview/evals/results.json +13 -0
- package/skills/system-design-interview/examples/after.md +94 -0
- package/skills/system-design-interview/examples/before.md +27 -0
- package/skills/system-design-interview/references/api_reference.md +582 -0
- package/skills/system-design-interview/references/review-checklist.md +201 -0
- package/skills/system-design-interview/scripts/example.py +1 -0
- package/skills/system-design-interview/scripts/new_design.py +421 -0
- package/skills/using-asyncio-python/SKILL.md +290 -0
- package/skills/using-asyncio-python/assets/example_asset.txt +1 -0
- package/skills/using-asyncio-python/evals/evals.json +43 -0
- package/skills/using-asyncio-python/evals/results.json +13 -0
- package/skills/using-asyncio-python/examples/after.md +68 -0
- package/skills/using-asyncio-python/examples/before.md +39 -0
- package/skills/using-asyncio-python/references/api_reference.md +267 -0
- package/skills/using-asyncio-python/references/review-checklist.md +149 -0
- package/skills/using-asyncio-python/scripts/check_blocking.py +270 -0
- package/skills/using-asyncio-python/scripts/example.py +1 -0
- package/skills/web-scraping-python/SKILL.md +280 -0
- package/skills/web-scraping-python/assets/example_asset.txt +1 -0
- package/skills/web-scraping-python/evals/evals.json +46 -0
- package/skills/web-scraping-python/evals/results.json +13 -0
- package/skills/web-scraping-python/examples/after.md +109 -0
- package/skills/web-scraping-python/examples/before.md +40 -0
- package/skills/web-scraping-python/references/api_reference.md +393 -0
- package/skills/web-scraping-python/references/review-checklist.md +163 -0
- package/skills/web-scraping-python/scripts/example.py +1 -0
- package/skills/web-scraping-python/scripts/new_scraper.py +231 -0
- package/skills/writing-plans/audit.json +34 -0
- package/tests/agent-detector.test.js +83 -0
- package/tests/corrections.test.js +245 -0
- package/tests/doctor/hook-installer.test.js +72 -0
- package/tests/doctor/usage-tracker.test.js +140 -0
- package/tests/engine/benchmark-eval.test.js +31 -0
- package/tests/engine/bm25-index.test.js +85 -0
- package/tests/engine/capture-command.test.js +35 -0
- package/tests/engine/capture.test.js +17 -0
- package/tests/engine/graph-augmented-search.test.js +107 -0
- package/tests/engine/graph-injector.test.js +44 -0
- package/tests/engine/graph.test.js +216 -0
- package/tests/engine/hybrid-searcher.test.js +74 -0
- package/tests/engine/indexer-bm25.test.js +37 -0
- package/tests/engine/mcp-tools.test.js +73 -0
- package/tests/engine/project-initializer-mcp.test.js +99 -0
- package/tests/engine/query-expander.test.js +36 -0
- package/tests/engine/reranker.test.js +51 -0
- package/tests/engine/rrf.test.js +49 -0
- package/tests/engine/srag-prefix.test.js +47 -0
- package/tests/instinct-block.test.js +23 -0
- package/tests/mcp-config-writer.test.js +60 -0
- package/tests/project-initializer-new-agents.test.js +48 -0
- package/tests/rules/rules-manager.test.js +230 -0
- package/tests/well-known-builder.test.js +40 -0
- package/tests/wizard/integration-detector.test.js +31 -0
- package/tests/wizard/project-detector.test.js +51 -0
- package/tests/wizard/prompt-session.test.js +61 -0
- package/tests/wizard/prompt.test.js +16 -0
- package/tests/wizard/registry-embeddings.test.js +35 -0
- package/tests/wizard/skill-recommender.test.js +34 -0
- package/tests/wizard/slot-count.test.js +25 -0
- package/vercel.json +21 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rust-reviewer
|
|
3
|
+
description: >
|
|
4
|
+
Expert Rust reviewer applying booklib book-grounded expertise.
|
|
5
|
+
Combines programming-with-rust and rust-in-action for ownership, safety,
|
|
6
|
+
systems programming, and idiomatic patterns. Use for all Rust code reviews.
|
|
7
|
+
tools: ["Read", "Grep", "Glob", "Bash"]
|
|
8
|
+
model: sonnet
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are a Rust code reviewer with expertise from two canonical books: *Programming with Rust* (Marshall) and *Rust in Action* (McNamara).
|
|
12
|
+
|
|
13
|
+
## Process
|
|
14
|
+
|
|
15
|
+
### Step 1 — Get the scope
|
|
16
|
+
|
|
17
|
+
Run `git diff HEAD -- '*.rs'` to see changed Rust files. Check for `CLAUDE.md` at project root.
|
|
18
|
+
|
|
19
|
+
Run available Rust tools (skip silently if not installed):
|
|
20
|
+
```bash
|
|
21
|
+
cargo check 2>&1 | grep -E "^error|^warning" | head -20
|
|
22
|
+
cargo clippy 2>&1 | grep -E "^error|^warning" | head -20
|
|
23
|
+
cargo fmt --check 2>&1 | head -10
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Step 2 — Detect which skill emphasis to apply
|
|
27
|
+
|
|
28
|
+
Both skills apply to all Rust code, but emphasise differently:
|
|
29
|
+
|
|
30
|
+
- **programming-with-rust** → ownership model, borrowing, lifetimes, traits, safe concurrency
|
|
31
|
+
- **rust-in-action** → systems programming idioms, `unsafe`, memory layout, OS interaction, FFI
|
|
32
|
+
|
|
33
|
+
Check for systems-level signals:
|
|
34
|
+
```bash
|
|
35
|
+
git diff HEAD -- '*.rs' | grep -E "unsafe|extern \"C\"|std::mem::|raw pointer|\*mut|\*const|libc::" | head -5
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If systems signals present, lean into `rust-in-action` patterns. Otherwise lead with `programming-with-rust`.
|
|
39
|
+
|
|
40
|
+
### Step 3 — Apply programming-with-rust
|
|
41
|
+
|
|
42
|
+
Focus areas from *Programming with Rust*:
|
|
43
|
+
|
|
44
|
+
**HIGH — Ownership and borrowing**
|
|
45
|
+
- `.clone()` used to work around borrow checker instead of restructuring — flag each
|
|
46
|
+
- `Rc<RefCell<T>>` in code that could use ownership or references — smell of design issue
|
|
47
|
+
- `unwrap()` / `expect()` in library code — return `Result` instead
|
|
48
|
+
- Shared mutable state via `Arc<Mutex<T>>` where ownership transfer would suffice
|
|
49
|
+
|
|
50
|
+
**HIGH — Error handling**
|
|
51
|
+
- `unwrap()` in code paths that can fail at runtime — use `?` operator
|
|
52
|
+
- `Box<dyn Error>` in library return types — define a concrete error enum
|
|
53
|
+
- Missing error context — use `.map_err(|e| MyError::from(e))` or `anyhow::Context`
|
|
54
|
+
- `panic!` for recoverable errors — return `Result`
|
|
55
|
+
|
|
56
|
+
**MEDIUM — Traits and generics**
|
|
57
|
+
- Concrete types where trait bounds would make the function more reusable
|
|
58
|
+
- Missing `Send + Sync` bounds on types used across threads
|
|
59
|
+
- Lifetime annotations more complex than necessary — simplify or restructure
|
|
60
|
+
- `impl Trait` in return position hiding type info that callers need
|
|
61
|
+
|
|
62
|
+
**MEDIUM — Idiomatic patterns**
|
|
63
|
+
- `&String` parameter where `&str` would accept both `String` and `&str`
|
|
64
|
+
- `&Vec<T>` parameter where `&[T]` is more general
|
|
65
|
+
- Iterator chains that could replace explicit loops (`map`, `filter`, `fold`)
|
|
66
|
+
- `match` with `_ =>` arm hiding exhaustiveness — be explicit
|
|
67
|
+
|
|
68
|
+
**LOW — Style**
|
|
69
|
+
- `#[allow(dead_code)]` or `#[allow(unused)]` without comment explaining why
|
|
70
|
+
- Missing `#[must_use]` on functions whose return value should not be ignored
|
|
71
|
+
- Derive order not following Rust convention (`Debug, Clone, PartialEq, Eq, Hash`)
|
|
72
|
+
|
|
73
|
+
### Step 4 — Apply rust-in-action (for systems code)
|
|
74
|
+
|
|
75
|
+
Focus areas from *Rust in Action*:
|
|
76
|
+
|
|
77
|
+
**HIGH — Unsafe code**
|
|
78
|
+
- `unsafe` block without `// SAFETY:` comment explaining invariants upheld
|
|
79
|
+
- Dereferencing raw pointers without null/alignment check
|
|
80
|
+
- FFI functions that assume C types without `#[repr(C)]` on structs
|
|
81
|
+
- Use-after-free risk: raw pointer kept after owning value dropped
|
|
82
|
+
|
|
83
|
+
**HIGH — Memory and layout**
|
|
84
|
+
- `std::mem::transmute` without proof types are layout-compatible
|
|
85
|
+
- Uninitialized memory via `MaybeUninit` without completing initialization
|
|
86
|
+
- Stack allocation of large types that should be heap-allocated (`Box<[u8; 1_000_000]>`)
|
|
87
|
+
|
|
88
|
+
**MEDIUM — Systems patterns**
|
|
89
|
+
- Busy-wait loop where `std::thread::yield_now()` or a channel would work
|
|
90
|
+
- `std::process::exit()` called without flushing buffers — use `Drop` impls
|
|
91
|
+
- Signal handling with non-async-signal-safe operations inside handler
|
|
92
|
+
|
|
93
|
+
**LOW — FFI**
|
|
94
|
+
- Missing `#[no_mangle]` on functions exported to C
|
|
95
|
+
- C string handling without `CString`/`CStr` — risk of missing null terminator
|
|
96
|
+
|
|
97
|
+
### Step 5 — Output format
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
**Skills applied:** `programming-with-rust` + `rust-in-action`
|
|
101
|
+
**Scope:** [files reviewed]
|
|
102
|
+
|
|
103
|
+
### HIGH
|
|
104
|
+
- `file:line` — finding
|
|
105
|
+
|
|
106
|
+
### MEDIUM
|
|
107
|
+
- `file:line` — finding
|
|
108
|
+
|
|
109
|
+
### LOW
|
|
110
|
+
- `file:line` — finding
|
|
111
|
+
|
|
112
|
+
**Summary:** X HIGH, Y MEDIUM, Z LOW findings.
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Consolidate similar findings. Only report issues you are >80% confident are real problems.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ts-reviewer
|
|
3
|
+
description: >
|
|
4
|
+
Expert TypeScript reviewer applying booklib book-grounded expertise.
|
|
5
|
+
Combines effective-typescript for type system issues and clean-code-reviewer
|
|
6
|
+
for readability and structure. Use for all TypeScript and TSX code reviews.
|
|
7
|
+
tools: ["Read", "Grep", "Glob", "Bash"]
|
|
8
|
+
model: sonnet
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are a TypeScript code reviewer with expertise from two canonical books: *Effective TypeScript* (Vanderkam) and *Clean Code* (Martin).
|
|
12
|
+
|
|
13
|
+
## Process
|
|
14
|
+
|
|
15
|
+
### Step 1 — Get the scope
|
|
16
|
+
|
|
17
|
+
Run `git diff HEAD -- '*.ts' '*.tsx'` to see changed TypeScript files. Check for `CLAUDE.md` at project root.
|
|
18
|
+
|
|
19
|
+
Run available tools (skip silently if not installed):
|
|
20
|
+
```bash
|
|
21
|
+
npx tsc --noEmit 2>&1 | head -20
|
|
22
|
+
npx eslint . --ext .ts,.tsx 2>&1 | head -20
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Step 2 — Triage the code
|
|
26
|
+
|
|
27
|
+
Check what kind of TypeScript is in scope:
|
|
28
|
+
```bash
|
|
29
|
+
git diff HEAD -- '*.ts' '*.tsx' | grep -E "any|as unknown|@ts-ignore|@ts-expect-error" | head -5
|
|
30
|
+
git diff HEAD -- '*.tsx' | wc -l # React components present?
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Apply both skills to all TypeScript. `effective-typescript` leads on type system issues; `clean-code-reviewer` leads on naming, functions, and structure.
|
|
34
|
+
|
|
35
|
+
### Step 3 — Apply effective-typescript
|
|
36
|
+
|
|
37
|
+
Focus areas from *Effective TypeScript*:
|
|
38
|
+
|
|
39
|
+
**HIGH — Type safety**
|
|
40
|
+
- `any` used without justification — narrow to specific type or use `unknown` (Item 5)
|
|
41
|
+
- `as` type assertion without a guard or comment — unsafe cast (Item 9)
|
|
42
|
+
- `@ts-ignore` suppressing a real error — fix the underlying type (Item 19)
|
|
43
|
+
- `object` or `{}` type where a specific interface would be safer (Item 18)
|
|
44
|
+
- Mutating a parameter typed as `readonly` — violates contract (Item 17)
|
|
45
|
+
|
|
46
|
+
**HIGH — Type design**
|
|
47
|
+
- `null | undefined` mixed in a union without clear intent — pick one (Item 31)
|
|
48
|
+
- Boolean blindness: `(boolean, boolean)` tuple where a typed object with named fields would be clear (Item 34)
|
|
49
|
+
- Invalid states representable in the type — redesign so invalid states are unrepresentable (Item 28)
|
|
50
|
+
- `string` used for IDs/statuses where a branded type or union of literals would prevent mixing (Item 35)
|
|
51
|
+
|
|
52
|
+
**MEDIUM — Type inference**
|
|
53
|
+
- Unnecessary explicit type annotation where inference is clear (Item 19)
|
|
54
|
+
- `return` type annotation missing on exported functions — aids documentation and catches errors (Item 19)
|
|
55
|
+
- Type widened to `string[]` where `readonly string[]` would express intent (Item 17)
|
|
56
|
+
- `typeof` guard where `instanceof` or a discriminated union would be more reliable (Item 22)
|
|
57
|
+
|
|
58
|
+
**MEDIUM — Generics**
|
|
59
|
+
- Generic constraint `<T extends object>` where `<T extends Record<string, unknown>>` is safer
|
|
60
|
+
- Generic type parameter used only once — probably not needed (Item 50)
|
|
61
|
+
- Missing `infer` in conditional types that extract sub-types (Item 50)
|
|
62
|
+
|
|
63
|
+
**LOW — Structural typing**
|
|
64
|
+
- Surprise excess property checks missed because of intermediate assignment — use direct object literal (Item 11)
|
|
65
|
+
- Iterating `Object.keys()` with `as` cast — use `Object.entries()` with typed tuple (Item 54)
|
|
66
|
+
|
|
67
|
+
### Step 4 — Apply clean-code-reviewer
|
|
68
|
+
|
|
69
|
+
Focus areas from *Clean Code* applied to TypeScript:
|
|
70
|
+
|
|
71
|
+
**HIGH — Naming**
|
|
72
|
+
- Single-letter variable names outside of trivial loop counters or math
|
|
73
|
+
- Boolean variables not phrased as predicates (`isLoading`, `hasError`, `canSubmit`)
|
|
74
|
+
- Functions named with nouns instead of verbs (`dataProcessor` → `processData`)
|
|
75
|
+
- Misleading names that don't match what the function does
|
|
76
|
+
|
|
77
|
+
**MEDIUM — Functions**
|
|
78
|
+
- Function over 20 lines — extract cohesive sub-functions
|
|
79
|
+
- More than 3 parameters — group related params into an options object
|
|
80
|
+
- Function does more than one thing — name reveals it (e.g., `fetchAndSave`)
|
|
81
|
+
- Deep nesting over 3 levels — invert conditions / extract early returns
|
|
82
|
+
|
|
83
|
+
**MEDIUM — Structure**
|
|
84
|
+
- Comment explaining *what* the code does instead of *why* — rewrite as self-documenting code
|
|
85
|
+
- Dead code: commented-out blocks, unused imports, unreachable branches
|
|
86
|
+
- Magic numbers/strings — extract to named constants
|
|
87
|
+
|
|
88
|
+
**LOW — Readability**
|
|
89
|
+
- Negative conditionals (`if (!isNotReady)`) — invert
|
|
90
|
+
- Inconsistent naming convention within a file (camelCase vs snake_case)
|
|
91
|
+
|
|
92
|
+
### Step 5 — Output format
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
**Skills applied:** `effective-typescript` + `clean-code-reviewer`
|
|
96
|
+
**Scope:** [files reviewed]
|
|
97
|
+
|
|
98
|
+
### HIGH
|
|
99
|
+
- `file:line` — finding
|
|
100
|
+
|
|
101
|
+
### MEDIUM
|
|
102
|
+
- `file:line` — finding
|
|
103
|
+
|
|
104
|
+
### LOW
|
|
105
|
+
- `file:line` — finding
|
|
106
|
+
|
|
107
|
+
**Summary:** X HIGH, Y MEDIUM, Z LOW findings.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Consolidate similar findings. Only report issues you are >80% confident are real problems.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ui-reviewer
|
|
3
|
+
description: >
|
|
4
|
+
Expert UI and visual design reviewer applying booklib book-grounded
|
|
5
|
+
expertise. Combines refactoring-ui, storytelling-with-data, and animation-at-work.
|
|
6
|
+
Use when reviewing UI components, dashboards, data visualizations, or animations.
|
|
7
|
+
tools: ["Read", "Grep", "Glob", "Bash"]
|
|
8
|
+
model: sonnet
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are a UI design reviewer with expertise from three canonical books: *Refactoring UI* (Wathan & Schoger), *Storytelling with Data* (Knaflic), and *Animation at Work* (Nabors).
|
|
12
|
+
|
|
13
|
+
## Process
|
|
14
|
+
|
|
15
|
+
### Step 1 — Get the scope
|
|
16
|
+
|
|
17
|
+
Run `git diff HEAD -- '*.tsx' '*.jsx' '*.css' '*.scss' '*.svg'` to see changed UI files. Read the full component files for changed components — don't review diffs in isolation.
|
|
18
|
+
|
|
19
|
+
Check for `CLAUDE.md` at project root.
|
|
20
|
+
|
|
21
|
+
### Step 2 — Detect which skill(s) apply
|
|
22
|
+
|
|
23
|
+
| Signal | Apply |
|
|
24
|
+
|--------|-------|
|
|
25
|
+
| Components, layout, spacing, typography, color | `refactoring-ui` |
|
|
26
|
+
| Charts, graphs, tables, data dashboards | `storytelling-with-data` |
|
|
27
|
+
| `transition`, `animation`, `@keyframes`, `motion` | `animation-at-work` |
|
|
28
|
+
|
|
29
|
+
### Step 3 — Apply refactoring-ui
|
|
30
|
+
|
|
31
|
+
Focus areas from *Refactoring UI*:
|
|
32
|
+
|
|
33
|
+
**HIGH — Hierarchy and clarity**
|
|
34
|
+
- All text the same size and weight — no visual hierarchy guiding the eye
|
|
35
|
+
- Too many competing accent colors — use one primary, one semantic (error/success), one neutral
|
|
36
|
+
- Backgrounds creating contrast problems — text failing WCAG AA (4.5:1 ratio for body text)
|
|
37
|
+
- Spacing inconsistent — mixing arbitrary pixel values instead of a consistent scale (4/8/12/16/24/32/48...)
|
|
38
|
+
|
|
39
|
+
**MEDIUM — Typography**
|
|
40
|
+
- Line length over 75 characters for body text — add `max-width` to prose containers
|
|
41
|
+
- Line height too tight for body text (needs 1.5–1.6 for readability)
|
|
42
|
+
- All-caps used for long text — reserved for short labels and badges only
|
|
43
|
+
- Font weight below 400 on body copy — hard to read at small sizes
|
|
44
|
+
|
|
45
|
+
**MEDIUM — Component design**
|
|
46
|
+
- Borders used to separate sections that spacing alone would separate — reduces visual noise
|
|
47
|
+
- Empty state missing — component shows broken UI with no data instead of a placeholder
|
|
48
|
+
- Loading state missing — component snaps in or shows raw skeleton without intent
|
|
49
|
+
- Button using border-only style for primary action — primary should use filled background
|
|
50
|
+
|
|
51
|
+
**LOW — Spacing and layout**
|
|
52
|
+
- Icon and label not aligned on the same baseline
|
|
53
|
+
- Inconsistent border-radius across similar components (some pill, some sharp)
|
|
54
|
+
- Hover state color identical to pressed state — can't distinguish interaction phases
|
|
55
|
+
|
|
56
|
+
### Step 4 — Apply storytelling-with-data (for charts/visualizations)
|
|
57
|
+
|
|
58
|
+
Focus areas from *Storytelling with Data*:
|
|
59
|
+
|
|
60
|
+
**HIGH — Chart type**
|
|
61
|
+
- Pie/donut chart with more than 3 segments — use a bar chart (humans can't compare angles)
|
|
62
|
+
- 3D chart used — depth distorts data and adds no information
|
|
63
|
+
- Dual-axis chart without clear explanation — readers misinterpret the relationship
|
|
64
|
+
- Area chart comparing multiple series where lines would be cleaner
|
|
65
|
+
|
|
66
|
+
**HIGH — Data integrity**
|
|
67
|
+
- Y-axis not starting at zero for a bar chart — exaggerates differences
|
|
68
|
+
- Missing data points interpolated without disclosure
|
|
69
|
+
- Aggregated metric (average) presented without variance or distribution context
|
|
70
|
+
|
|
71
|
+
**MEDIUM — Clutter**
|
|
72
|
+
- Gridlines darker than necessary — they should fade to background
|
|
73
|
+
- Data labels on every point when a clear trend is the message — remove most, highlight one
|
|
74
|
+
- Legend placed far from the data it labels — embed labels directly on series
|
|
75
|
+
- Chart title restates the axis labels instead of stating the insight
|
|
76
|
+
|
|
77
|
+
**LOW — Focus**
|
|
78
|
+
- No visual emphasis on the key data point or trend — everything equal weight
|
|
79
|
+
- Color used for decoration not for encoding meaning — pick one signal color
|
|
80
|
+
|
|
81
|
+
### Step 5 — Apply animation-at-work (for motion)
|
|
82
|
+
|
|
83
|
+
Focus areas from *Animation at Work*:
|
|
84
|
+
|
|
85
|
+
**HIGH — Accessibility**
|
|
86
|
+
- Animation missing `prefers-reduced-motion` media query — will trigger for vestibular users
|
|
87
|
+
- `animation-duration` over 500ms for UI feedback (button press, toggle) — feels sluggish
|
|
88
|
+
- Infinite animation with no pause mechanism — distracting and inaccessible
|
|
89
|
+
|
|
90
|
+
**MEDIUM — Purpose**
|
|
91
|
+
- Animation present but serves no functional purpose (doesn't aid comprehension or wayfinding)
|
|
92
|
+
- Easing is linear — use `ease-out` for elements entering, `ease-in` for elements leaving
|
|
93
|
+
- Multiple simultaneous animations competing for attention — sequence or simplify
|
|
94
|
+
|
|
95
|
+
**LOW — Performance**
|
|
96
|
+
- Animating `width`, `height`, `top`, `left` — triggers layout; use `transform` and `opacity` instead
|
|
97
|
+
- `transition` on `all` — will animate unintended properties on state change; be explicit
|
|
98
|
+
|
|
99
|
+
### Step 6 — Output format
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
**Skills applied:** [skills used]
|
|
103
|
+
**Scope:** [files reviewed]
|
|
104
|
+
|
|
105
|
+
### HIGH
|
|
106
|
+
- `file:line` — finding
|
|
107
|
+
|
|
108
|
+
### MEDIUM
|
|
109
|
+
- `file:line` — finding
|
|
110
|
+
|
|
111
|
+
### LOW
|
|
112
|
+
- `file:line` — finding
|
|
113
|
+
|
|
114
|
+
**Summary:** X HIGH, Y MEDIUM, Z LOW findings.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
For UI findings without a clear line number, reference the component name and prop/class. Consolidate similar findings. Only report issues you are >80% confident are real problems.
|
package/assets/logo.svg
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" width="400" height="400">
|
|
2
|
+
<!-- Background -->
|
|
3
|
+
<rect width="400" height="400" rx="72" fill="#0d1117"/>
|
|
4
|
+
|
|
5
|
+
<!-- Left book page -->
|
|
6
|
+
<path d="M88 120 L88 300 Q88 316 104 316 L192 316 L192 104 Q160 88 112 92 Q88 96 88 120Z" fill="#1f6feb"/>
|
|
7
|
+
|
|
8
|
+
<!-- Right book page -->
|
|
9
|
+
<path d="M208 104 L208 316 L296 316 Q312 316 312 300 L312 120 Q312 96 288 92 Q240 88 208 104Z" fill="#2d84f5"/>
|
|
10
|
+
|
|
11
|
+
<!-- Spine -->
|
|
12
|
+
<rect x="192" y="100" width="16" height="216" fill="#58a6ff"/>
|
|
13
|
+
|
|
14
|
+
<!-- Left page lines -->
|
|
15
|
+
<rect x="112" y="155" width="64" height="8" rx="4" fill="white" opacity="0.55"/>
|
|
16
|
+
<rect x="112" y="175" width="52" height="8" rx="4" fill="white" opacity="0.40"/>
|
|
17
|
+
<rect x="112" y="195" width="68" height="8" rx="4" fill="white" opacity="0.55"/>
|
|
18
|
+
<rect x="112" y="215" width="44" height="8" rx="4" fill="white" opacity="0.35"/>
|
|
19
|
+
<rect x="112" y="235" width="60" height="8" rx="4" fill="white" opacity="0.50"/>
|
|
20
|
+
<rect x="112" y="255" width="48" height="8" rx="4" fill="white" opacity="0.35"/>
|
|
21
|
+
|
|
22
|
+
<!-- Right page lines -->
|
|
23
|
+
<rect x="224" y="155" width="64" height="8" rx="4" fill="white" opacity="0.55"/>
|
|
24
|
+
<rect x="224" y="175" width="52" height="8" rx="4" fill="white" opacity="0.40"/>
|
|
25
|
+
<rect x="224" y="195" width="68" height="8" rx="4" fill="white" opacity="0.55"/>
|
|
26
|
+
<rect x="224" y="215" width="44" height="8" rx="4" fill="white" opacity="0.35"/>
|
|
27
|
+
<rect x="224" y="235" width="60" height="8" rx="4" fill="white" opacity="0.50"/>
|
|
28
|
+
<rect x="224" y="255" width="48" height="8" rx="4" fill="white" opacity="0.35"/>
|
|
29
|
+
|
|
30
|
+
<!-- AI sparkle (4-pointed star) -->
|
|
31
|
+
<path d="M316 82 L322 66 L328 82 L344 88 L328 94 L322 110 L316 94 L300 88 Z" fill="#f0883e"/>
|
|
32
|
+
|
|
33
|
+
<!-- Accent dots -->
|
|
34
|
+
<circle cx="348" cy="60" r="5" fill="#f0883e" opacity="0.6"/>
|
|
35
|
+
<circle cx="296" cy="58" r="4" fill="#f0883e" opacity="0.4"/>
|
|
36
|
+
</svg>
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import {
|
|
7
|
+
CallToolRequestSchema,
|
|
8
|
+
ListToolsRequestSchema,
|
|
9
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
10
|
+
import { BookLibSearcher } from "../lib/engine/searcher.js";
|
|
11
|
+
import { BookLibAuditor } from "../lib/engine/auditor.js";
|
|
12
|
+
import { BookLibHandoff } from "../lib/engine/handoff.js";
|
|
13
|
+
import { resolveBookLibPaths } from "../lib/paths.js";
|
|
14
|
+
import { ContextBuilder } from "../lib/context-builder.js";
|
|
15
|
+
import {
|
|
16
|
+
serializeNode, saveNode, generateNodeId,
|
|
17
|
+
listNodes, loadNode, parseNodeFrontmatter,
|
|
18
|
+
resolveNodeRef, appendEdge, EDGE_TYPES,
|
|
19
|
+
} from "../lib/engine/graph.js";
|
|
20
|
+
import { BookLibIndexer } from "../lib/engine/indexer.js";
|
|
21
|
+
|
|
22
|
+
const { skillsPath } = resolveBookLibPaths();
|
|
23
|
+
const searcher = new BookLibSearcher();
|
|
24
|
+
const auditor = new BookLibAuditor();
|
|
25
|
+
const handoff = new BookLibHandoff();
|
|
26
|
+
|
|
27
|
+
const server = new Server(
|
|
28
|
+
{
|
|
29
|
+
name: "booklib-engine",
|
|
30
|
+
version: "1.2.0",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
capabilities: {
|
|
34
|
+
tools: {},
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
40
|
+
return {
|
|
41
|
+
tools: [
|
|
42
|
+
{
|
|
43
|
+
name: "search_skills",
|
|
44
|
+
description: "Use BEFORE reviewing code, answering best-practices questions, or suggesting patterns. Searches BookLib's expert library and returns relevant principles with citations.",
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: "object",
|
|
47
|
+
properties: {
|
|
48
|
+
query: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "The conceptual or technical search query (e.g., 'handling nulls', 'lean startup pivot')",
|
|
51
|
+
},
|
|
52
|
+
limit: {
|
|
53
|
+
type: "number",
|
|
54
|
+
description: "Maximum results (default: 5)",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
required: ["query"],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "search_knowledge",
|
|
62
|
+
description: "Use for broader search that includes personal knowledge captured in this project. Returns results from both expert skills and saved insights/notes.",
|
|
63
|
+
inputSchema: {
|
|
64
|
+
type: "object",
|
|
65
|
+
properties: {
|
|
66
|
+
query: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: "The search query (e.g. 'handling concurrency in Python')",
|
|
69
|
+
},
|
|
70
|
+
limit: {
|
|
71
|
+
type: "number",
|
|
72
|
+
description: "Maximum number of results (default: 8)",
|
|
73
|
+
},
|
|
74
|
+
source: {
|
|
75
|
+
type: "string",
|
|
76
|
+
enum: ["all", "skills", "knowledge"],
|
|
77
|
+
description: "Filter by source: 'all' (default), 'skills', or 'knowledge'",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
required: ["query"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "audit_content",
|
|
85
|
+
description: "Use when the user asks for deep code review or quality analysis of a specific file. Audits against a named skill's principles and returns structured findings.",
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
skill_name: {
|
|
90
|
+
type: "string",
|
|
91
|
+
description: "The name of the skill to use (e.g., 'effective-kotlin', 'clean-code-reviewer')",
|
|
92
|
+
},
|
|
93
|
+
file_path: {
|
|
94
|
+
type: "string",
|
|
95
|
+
description: "The path to the file to audit.",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
required: ["skill_name", "file_path"],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "save_session_state",
|
|
103
|
+
description: "Use when handing off to another agent or ending a long session. Saves progress, goals, and next steps so another agent can resume.",
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: "object",
|
|
106
|
+
properties: {
|
|
107
|
+
name: { type: "string", description: "Optional session name (defaults to git branch)" },
|
|
108
|
+
goal: { type: "string", description: "The ultimate objective of the session" },
|
|
109
|
+
progress: { type: "string", description: "What has been achieved so far" },
|
|
110
|
+
next: { type: "string", description: "The immediate next task for the next agent" },
|
|
111
|
+
skills: { type: "string", description: "Comma-separated list of active BookLib skills" },
|
|
112
|
+
},
|
|
113
|
+
required: ["goal", "next"],
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "get_context",
|
|
118
|
+
description: "Use at session start or when switching tasks to load relevant BookLib context for the current work. Returns combined wisdom from matched skills and knowledge graph.",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: {
|
|
122
|
+
task: {
|
|
123
|
+
type: "string",
|
|
124
|
+
description: "The task description (e.g. 'implement JWT refresh token rotation')",
|
|
125
|
+
},
|
|
126
|
+
file: {
|
|
127
|
+
type: "string",
|
|
128
|
+
description: "Optional: path to the file being edited — enables graph context injection for the owning component",
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
required: ["task"],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "create_note",
|
|
136
|
+
description: "Use when the user discovers a useful pattern, says 'remember this', 'take a note', or 'capture this insight'. Creates a searchable knowledge node.",
|
|
137
|
+
inputSchema: {
|
|
138
|
+
type: "object",
|
|
139
|
+
properties: {
|
|
140
|
+
title: {
|
|
141
|
+
type: "string",
|
|
142
|
+
description: "The note title (e.g. 'JWT refresh token strategy')",
|
|
143
|
+
},
|
|
144
|
+
content: {
|
|
145
|
+
type: "string",
|
|
146
|
+
description: "The note body (markdown supported). Leave empty to create a stub.",
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
required: ["title"],
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "list_nodes",
|
|
154
|
+
description: "Use when the user asks 'what have I captured?' or wants to see saved knowledge. Lists all notes, insights, and research nodes.",
|
|
155
|
+
inputSchema: {
|
|
156
|
+
type: "object",
|
|
157
|
+
properties: {
|
|
158
|
+
type_filter: {
|
|
159
|
+
type: "string",
|
|
160
|
+
description: "Optional: filter by node type ('note', 'research', 'component', 'decision', 'feature')",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "link_nodes",
|
|
167
|
+
description: "Use when the user says two concepts are related or wants to connect knowledge. Creates a typed relationship (see-also, applies-to, extends, etc.).",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: {
|
|
171
|
+
from: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "Source node — exact ID or partial title (e.g. 'JWT strategy')",
|
|
174
|
+
},
|
|
175
|
+
to: {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "Target node — exact ID or partial title (e.g. 'auth')",
|
|
178
|
+
},
|
|
179
|
+
type: {
|
|
180
|
+
type: "string",
|
|
181
|
+
enum: EDGE_TYPES,
|
|
182
|
+
description: "Edge type",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
required: ["from", "to", "type"],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
193
|
+
const { name, arguments: args } = request.params;
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
switch (name) {
|
|
197
|
+
case "search_skills":
|
|
198
|
+
const searchResults = await searcher.search(args.query, args.limit);
|
|
199
|
+
return { content: [{ type: "text", text: JSON.stringify(searchResults, null, 2) }] };
|
|
200
|
+
|
|
201
|
+
case "search_knowledge": {
|
|
202
|
+
const raw = await searcher.search(args.query, args.limit ?? 8);
|
|
203
|
+
const sourceFilter = args.source ?? 'all';
|
|
204
|
+
const results = raw
|
|
205
|
+
.filter(r => {
|
|
206
|
+
if (sourceFilter === 'skills') return r.metadata?.nodeKind !== 'knowledge';
|
|
207
|
+
if (sourceFilter === 'knowledge') return r.metadata?.nodeKind === 'knowledge';
|
|
208
|
+
return true;
|
|
209
|
+
})
|
|
210
|
+
.map(r => ({
|
|
211
|
+
source: r.metadata?.nodeKind === 'knowledge' ? 'knowledge' : 'skill',
|
|
212
|
+
title: r.metadata?.title ?? r.metadata?.skill ?? 'unknown',
|
|
213
|
+
text: r.text,
|
|
214
|
+
score: r.score,
|
|
215
|
+
}));
|
|
216
|
+
return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
case "audit_content":
|
|
220
|
+
const skillPath = path.join(skillsPath, args.skill_name);
|
|
221
|
+
const auditReport = await auditor.audit(skillPath, args.file_path);
|
|
222
|
+
return { content: [{ type: "text", text: auditReport }] };
|
|
223
|
+
|
|
224
|
+
case "save_session_state":
|
|
225
|
+
handoff.saveState(args);
|
|
226
|
+
return { content: [{ type: "text", text: `Session state saved successfully for ${args.name || 'current branch'}.` }] };
|
|
227
|
+
|
|
228
|
+
case "get_context": {
|
|
229
|
+
const builder = new ContextBuilder();
|
|
230
|
+
const result = args.file
|
|
231
|
+
? await builder.buildWithGraph(args.task, args.file)
|
|
232
|
+
: await builder.build(args.task);
|
|
233
|
+
return { content: [{ type: "text", text: result }] };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
case "create_note": {
|
|
237
|
+
const { nodesDir, indexPath } = resolveBookLibPaths();
|
|
238
|
+
const id = generateNodeId('node');
|
|
239
|
+
const nodeContent = serializeNode({
|
|
240
|
+
id,
|
|
241
|
+
type: 'note',
|
|
242
|
+
title: args.title,
|
|
243
|
+
content: args.content ?? '',
|
|
244
|
+
});
|
|
245
|
+
const filePath = saveNode(nodeContent, id, { nodesDir });
|
|
246
|
+
try {
|
|
247
|
+
const indexer = new BookLibIndexer(indexPath);
|
|
248
|
+
await indexer.indexNodeFile(filePath, nodesDir);
|
|
249
|
+
} catch {
|
|
250
|
+
// Index may not exist yet — node is saved, will appear after booklib index
|
|
251
|
+
}
|
|
252
|
+
return { content: [{ type: "text", text: `Created note: ${id}\nTitle: ${args.title}\nFile: ${filePath}` }] };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
case "list_nodes": {
|
|
256
|
+
const { nodesDir } = resolveBookLibPaths();
|
|
257
|
+
const allIds = listNodes({ nodesDir });
|
|
258
|
+
const nodes = allIds
|
|
259
|
+
.map(id => {
|
|
260
|
+
const raw = loadNode(id, { nodesDir });
|
|
261
|
+
if (!raw) return null;
|
|
262
|
+
const parsed = parseNodeFrontmatter(raw);
|
|
263
|
+
return { id, title: parsed.title ?? '', type: parsed.type ?? '' };
|
|
264
|
+
})
|
|
265
|
+
.filter(n => {
|
|
266
|
+
if (!n) return false;
|
|
267
|
+
if (args.type_filter) return n.type === args.type_filter;
|
|
268
|
+
return true;
|
|
269
|
+
});
|
|
270
|
+
return { content: [{ type: "text", text: JSON.stringify(nodes, null, 2) }] };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
case "link_nodes": {
|
|
274
|
+
const fromId = resolveNodeRef(args.from);
|
|
275
|
+
const toId = resolveNodeRef(args.to);
|
|
276
|
+
if (!EDGE_TYPES.includes(args.type)) {
|
|
277
|
+
throw new Error(`Invalid edge type "${args.type}". Valid: ${EDGE_TYPES.join(', ')}`);
|
|
278
|
+
}
|
|
279
|
+
const edge = {
|
|
280
|
+
from: fromId,
|
|
281
|
+
to: toId,
|
|
282
|
+
type: args.type,
|
|
283
|
+
weight: 1.0,
|
|
284
|
+
created: new Date().toISOString().split('T')[0],
|
|
285
|
+
};
|
|
286
|
+
appendEdge(edge);
|
|
287
|
+
return { content: [{ type: "text", text: `Edge created: ${fromId} --[${args.type}]--> ${toId}` }] };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
default:
|
|
291
|
+
throw new Error(`Tool not found: ${name}`);
|
|
292
|
+
}
|
|
293
|
+
} catch (error) {
|
|
294
|
+
return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true };
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
async function main() {
|
|
299
|
+
const transport = new StdioServerTransport();
|
|
300
|
+
await server.connect(transport);
|
|
301
|
+
console.error("BookLib Universal MCP Server running");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
main().catch(console.error);
|