wicked-garden 12.27.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/.claude-plugin/archetypes.json +166 -0
- package/.claude-plugin/components.json +75 -0
- package/.claude-plugin/marketplace.json +15 -0
- package/.claude-plugin/plugin.json +174 -0
- package/.claude-plugin/specialist.json +48 -0
- package/.claude-plugin/stack-registry.json +96 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +712 -0
- package/CONTRIBUTING.md +99 -0
- package/ETHOS.md +83 -0
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/WICKED_GARDEN_BUS_EVENTS.md +149 -0
- package/agents/agentic/architect.md +449 -0
- package/agents/agentic/performance-analyst.md +702 -0
- package/agents/agentic/safety-reviewer.md +662 -0
- package/agents/crew/implementer.md +163 -0
- package/agents/crew/researcher.md +94 -0
- package/agents/crew/reviewer.md +184 -0
- package/agents/data/data-engineer.md +227 -0
- package/agents/engineering/api-documentarian.md +440 -0
- package/agents/engineering/migration-engineer.md +301 -0
- package/agents/engineering/solution-architect.md +208 -0
- package/agents/jam/brainstorm-facilitator.md +297 -0
- package/agents/jam/council.md +322 -0
- package/agents/jam/quick-facilitator.md +85 -0
- package/agents/persona/persona-agent.md +121 -0
- package/agents/platform/compliance-officer.md +266 -0
- package/agents/platform/privacy-expert.md +496 -0
- package/agents/platform/security-engineer.md +287 -0
- package/agents/product/a11y-expert.md +323 -0
- package/agents/product/requirements-analyst.md +238 -0
- package/agents/product/ui-reviewer.md +180 -0
- package/agents/product/ux-designer.md +199 -0
- package/agents/product/value-strategist.md +269 -0
- package/agents/qe/semantic-reviewer.md +78 -0
- package/commands/agentic/audit.md +24 -0
- package/commands/agentic/design.md +24 -0
- package/commands/agentic/frameworks.md +25 -0
- package/commands/agentic/review.md +27 -0
- package/commands/archetype/build.md +12 -0
- package/commands/archetype/decide.md +12 -0
- package/commands/archetype/explore.md +12 -0
- package/commands/archetype/incident.md +12 -0
- package/commands/archetype/migrate.md +12 -0
- package/commands/archetype/modernize.md +12 -0
- package/commands/archetype/review.md +14 -0
- package/commands/archetype/ship.md +12 -0
- package/commands/archetype/specify.md +12 -0
- package/commands/archetype/triage.md +12 -0
- package/commands/compile.md +37 -0
- package/commands/data/analyze.md +18 -0
- package/commands/data/data.md +21 -0
- package/commands/data/ml.md +18 -0
- package/commands/data/ontology.md +22 -0
- package/commands/data/pipeline.md +17 -0
- package/commands/deliberate.md +181 -0
- package/commands/engineering/add-field.md +77 -0
- package/commands/engineering/apply.md +58 -0
- package/commands/engineering/arch.md +26 -0
- package/commands/engineering/debug.md +27 -0
- package/commands/engineering/docs.md +27 -0
- package/commands/engineering/new-generator.md +257 -0
- package/commands/engineering/patch-plan.md +59 -0
- package/commands/engineering/plan.md +29 -0
- package/commands/engineering/remove.md +48 -0
- package/commands/engineering/rename.md +44 -0
- package/commands/engineering/review.md +32 -0
- package/commands/help.md +128 -0
- package/commands/install.md +118 -0
- package/commands/intent.md +54 -0
- package/commands/jam/brainstorm.md +37 -0
- package/commands/jam/council.md +49 -0
- package/commands/jam/quick.md +21 -0
- package/commands/jam/revisit.md +79 -0
- package/commands/persona/as.md +136 -0
- package/commands/persona/define.md +24 -0
- package/commands/persona/list.md +118 -0
- package/commands/platform/actions.md +20 -0
- package/commands/platform/assert.md +18 -0
- package/commands/platform/audit.md +23 -0
- package/commands/platform/compliance.md +20 -0
- package/commands/platform/gh.md +22 -0
- package/commands/platform/health.md +22 -0
- package/commands/platform/incident.md +23 -0
- package/commands/platform/infra.md +24 -0
- package/commands/platform/peer-health.md +103 -0
- package/commands/platform/plugin-health.md +58 -0
- package/commands/platform/security.md +38 -0
- package/commands/platform/toolchain.md +96 -0
- package/commands/platform/traces.md +20 -0
- package/commands/product/a11y.md +19 -0
- package/commands/product/acceptance.md +19 -0
- package/commands/product/align.md +20 -0
- package/commands/product/analyze.md +23 -0
- package/commands/product/elicit.md +19 -0
- package/commands/product/listen.md +24 -0
- package/commands/product/mockup.md +20 -0
- package/commands/product/screenshot.md +19 -0
- package/commands/product/strategy.md +40 -0
- package/commands/product/synthesize.md +23 -0
- package/commands/product/ux-review.md +42 -0
- package/commands/product/ux.md +20 -0
- package/commands/product/visual-direction.md +34 -0
- package/commands/prove.md +47 -0
- package/commands/report-issue.md +243 -0
- package/commands/reset.md +144 -0
- package/commands/search/blast-radius.md +58 -0
- package/commands/search/hotspots.md +55 -0
- package/commands/search/index.md +38 -0
- package/commands/search/lineage.md +47 -0
- package/commands/search/service-map.md +79 -0
- package/commands/setup.md +363 -0
- package/commands/smaht/briefing.md +200 -0
- package/commands/smaht/events-import.md +95 -0
- package/commands/smaht/state.md +19 -0
- package/commands/where-am-i.md +58 -0
- package/docs/README.md +32 -0
- package/docs/adr/0001-code-relationship-graph-engine.md +116 -0
- package/docs/adr/0002-major-cleanup-keep-cut.md +91 -0
- package/docs/adr/0003-peers-gate-required-layers-optin.md +41 -0
- package/docs/adr/0004-code-graph-moves-to-wicked-brain.md +47 -0
- package/docs/brain-chunk-format.md +135 -0
- package/docs/compiler.md +95 -0
- package/docs/daemon-api.md +70 -0
- package/docs/domains.md +197 -0
- package/docs/getting-started.md +208 -0
- package/docs/plans/2026-06-08-wicked-loom-conduct.md +1337 -0
- package/docs/plans/2026-06-08-wicked-loom-contract.md +638 -0
- package/docs/plans/2026-06-08-wicked-loom-cutover.md +1300 -0
- package/docs/plans/2026-06-08-wicked-loom-expand-compose.md +843 -0
- package/docs/plans/2026-06-08-wicked-loom-flow-cutover.md +403 -0
- package/docs/plans/2026-06-10-codegraph-to-brain-phase1a-graph-core.md +838 -0
- package/docs/plans/2026-06-10-codegraph-to-brain-phase1b-injected-edges.md +44 -0
- package/docs/required-peers.md +60 -0
- package/docs/specs/2026-06-08-wicked-loom-extraction.md +225 -0
- package/docs/specs/2026-06-10-codegraph-to-brain-migration.md +168 -0
- package/docs/v11/archetypes.md +231 -0
- package/hooks/hooks.json +275 -0
- package/hooks/scripts/bootstrap.py +1797 -0
- package/hooks/scripts/invoke.py +62 -0
- package/hooks/scripts/notification.py +166 -0
- package/hooks/scripts/permission_request.py +223 -0
- package/hooks/scripts/post_tool.py +1374 -0
- package/hooks/scripts/pre_compact.py +272 -0
- package/hooks/scripts/pre_tool.py +1278 -0
- package/hooks/scripts/prompt_submit.py +1109 -0
- package/hooks/scripts/session_end.py +95 -0
- package/hooks/scripts/stop.py +624 -0
- package/hooks/scripts/subagent_lifecycle.py +464 -0
- package/hooks/scripts/subscribers/on_gate_decided.py +84 -0
- package/hooks/scripts/task_completed.py +322 -0
- package/hooks/scripts/worktree_guard.py +148 -0
- package/hooks/subscriptions/on_gate_decided.json +9 -0
- package/install.mjs +128 -0
- package/package.json +41 -0
- package/pyproject.toml +59 -0
- package/schemas/README.md +32 -0
- package/schemas/assert_contracts.json +37 -0
- package/schemas/health_probe.json +46 -0
- package/schemas/plugin_status.json +37 -0
- package/scripts/_adapters/__init__.py +166 -0
- package/scripts/_adapters/jira_adapter.py +18 -0
- package/scripts/_adapters/linear_adapter.py +18 -0
- package/scripts/_adapters/miro_adapter.py +18 -0
- package/scripts/_adapters/notion_adapter.py +18 -0
- package/scripts/_agents.py +357 -0
- package/scripts/_brain_ingest/__init__.py +2 -0
- package/scripts/_brain_ingest/session_fact_extractor.py +341 -0
- package/scripts/_brain_port.py +163 -0
- package/scripts/_bus.py +1081 -0
- package/scripts/_bus_catalog_gen.py +93 -0
- package/scripts/_bus_consumers.json +46 -0
- package/scripts/_bus_emit.py +43 -0
- package/scripts/_capability_registry.py +334 -0
- package/scripts/_capability_resolver.py +322 -0
- package/scripts/_domain_store.py +559 -0
- package/scripts/_event_log_reader.py +154 -0
- package/scripts/_event_schema.py +305 -0
- package/scripts/_event_store.py +397 -0
- package/scripts/_heavy_cadence.py +324 -0
- package/scripts/_integration_resolver.py +321 -0
- package/scripts/_logger.py +151 -0
- package/scripts/_loom.py +482 -0
- package/scripts/_paths.py +133 -0
- package/scripts/_python.sh +22 -0
- package/scripts/_run.py +137 -0
- package/scripts/_session.py +502 -0
- package/scripts/_validate_registry.py +1042 -0
- package/scripts/_wicked_testing_probe.py +277 -0
- package/scripts/agentic/analyze_agents.py +391 -0
- package/scripts/agentic/detect_framework.py +420 -0
- package/scripts/agentic/issue_taxonomy.py +357 -0
- package/scripts/agentic/pattern_scorer.py +434 -0
- package/scripts/classify/persist.py +169 -0
- package/scripts/compiler/compile.py +552 -0
- package/scripts/compiler/phase0/VERDICT.md +60 -0
- package/scripts/compiler/phase0/detect.py +292 -0
- package/scripts/compiler/phase0/emit.py +228 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.bindings.json +30 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/honest-tests.txt +2 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/command_iq.bindings.json +45 -0
- package/scripts/compiler/phase0/evidence/command_iq.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/honest-tests.txt +3 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/memos.bindings.json +28 -0
- package/scripts/compiler/phase0/evidence/memos.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/honest-tests.txt +2 -0
- package/scripts/compiler/phase0/evidence/memos.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/memos.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/memos.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/memos.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/verdict.json +104 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.bindings.json +29 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/honest-tests.txt +3 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/wire-vault-transcript.txt +60 -0
- package/scripts/compiler/phase0/run_probe.py +234 -0
- package/scripts/compiler/phase0/wire_vault.py +310 -0
- package/scripts/crew/__init__.py +0 -0
- package/scripts/crew/_task_audit_writer.py +243 -0
- package/scripts/crew/_task_reader.py +389 -0
- package/scripts/crew/archetypes_v11.py +348 -0
- package/scripts/crew/detectors/__init__.py +12 -0
- package/scripts/crew/flow_compiler.py +121 -0
- package/scripts/crew/phase_manager.py +703 -0
- package/scripts/crew/scope_delta.py +264 -0
- package/scripts/crew/specialist_resolver.py +218 -0
- package/scripts/crew/stack_registry.py +189 -0
- package/scripts/data/data_profiler.py +271 -0
- package/scripts/data/ontology_recommender.py +231 -0
- package/scripts/data/schema_validator.py +267 -0
- package/scripts/delivery/drift.py +739 -0
- package/scripts/delivery/telemetry.py +614 -0
- package/scripts/engineering/patch/codegraph_db.py +125 -0
- package/scripts/engineering/patch/generators/__init__.py +56 -0
- package/scripts/engineering/patch/generators/base.py +373 -0
- package/scripts/engineering/patch/generators/csharp_generator.py +494 -0
- package/scripts/engineering/patch/generators/go_generator.py +430 -0
- package/scripts/engineering/patch/generators/java_generator.py +928 -0
- package/scripts/engineering/patch/generators/jsp_generator.py +454 -0
- package/scripts/engineering/patch/generators/kotlin_generator.py +561 -0
- package/scripts/engineering/patch/generators/perl_generator.py +510 -0
- package/scripts/engineering/patch/generators/php_generator.py +644 -0
- package/scripts/engineering/patch/generators/propagation_engine.py +929 -0
- package/scripts/engineering/patch/generators/python_generator.py +487 -0
- package/scripts/engineering/patch/generators/ruby_generator.py +463 -0
- package/scripts/engineering/patch/generators/rust_generator.py +400 -0
- package/scripts/engineering/patch/generators/sql_generator.py +594 -0
- package/scripts/engineering/patch/generators/typescript_generator.py +439 -0
- package/scripts/engineering/patch/patch.py +800 -0
- package/scripts/engineering/patch/safety.py +429 -0
- package/scripts/jam/__init__.py +0 -0
- package/scripts/jam/_bus_consumers.py +271 -0
- package/scripts/jam/agentic_cli_registry.py +703 -0
- package/scripts/jam/consensus.py +737 -0
- package/scripts/jam/detect_clis.py +409 -0
- package/scripts/jam/jam.py +283 -0
- package/scripts/jam/save_transcript.py +171 -0
- package/scripts/loom/__init__.py +22 -0
- package/scripts/loom/cli.py +170 -0
- package/scripts/loom/compose.py +180 -0
- package/scripts/loom/gate.py +120 -0
- package/scripts/loom/manifest.py +140 -0
- package/scripts/loom/resolve.py +59 -0
- package/scripts/persona/__init__.py +0 -0
- package/scripts/persona/registry.py +688 -0
- package/scripts/platform/guard_pipeline.py +1214 -0
- package/scripts/platform/guard_profiles.py +216 -0
- package/scripts/platform/observability/assert_contracts.py +434 -0
- package/scripts/platform/observability/health_probe.py +915 -0
- package/scripts/platform/observability/ops_log_viewer.py +209 -0
- package/scripts/platform/prereq_doctor.py +567 -0
- package/scripts/qe/conditions_manifest.py +260 -0
- package/scripts/qe/content_sanitizer.py +160 -0
- package/scripts/qe/coverage_tracker.py +535 -0
- package/scripts/qe/discover_scenarios.py +243 -0
- package/scripts/qe/evidence_tracker.py +232 -0
- package/scripts/qe/prove.py +196 -0
- package/scripts/qe/registry_lookup.py +80 -0
- package/scripts/qe/registry_store.py +176 -0
- package/scripts/qe/semantic_review.py +1005 -0
- package/scripts/qe/vault_gate.py +382 -0
- package/scripts/qe/verdict_audit.py +175 -0
- package/scripts/qe/verdict_schema.py +335 -0
- package/scripts/reset.py +220 -0
- package/scripts/resolve_path.py +22 -0
- package/scripts/sentinel/invariants.py +402 -0
- package/scripts/sentinel/pre_push.py +73 -0
- package/scripts/setup/__init__.py +1 -0
- package/scripts/setup/detect_state.py +114 -0
- package/scripts/setup/migrate_legacy.py +67 -0
- package/scripts/setup/migrate_v6_projects.py +232 -0
- package/scripts/setup/onboarding.py +114 -0
- package/scripts/smaht/_bus_consumers.py +98 -0
- package/scripts/smaht/adapters/__init__.py +83 -0
- package/scripts/smaht/adapters/brain_adapter.py +254 -0
- package/scripts/smaht/adapters/context7_adapter.py +438 -0
- package/scripts/smaht/adapters/delegation_adapter.py +104 -0
- package/scripts/smaht/adapters/domain_adapter.py +206 -0
- package/scripts/smaht/adapters/events_adapter.py +231 -0
- package/scripts/smaht/adapters/tools_adapter.py +49 -0
- package/scripts/smaht/cheatsheet_store.py +236 -0
- package/scripts/smaht/context_package.py +386 -0
- package/scripts/smaht/knowledge_graph.py +395 -0
- package/scripts/smaht/propose_skills.py +856 -0
- package/scripts/smaht/test_cheatsheet_store.py +428 -0
- package/scripts/statusline.py +151 -0
- package/scripts/where_am_i.py +236 -0
- package/skills/agentic/agentic-patterns/SKILL.md +91 -0
- package/skills/agentic/agentic-patterns/refs/anti-patterns-design.md +283 -0
- package/skills/agentic/agentic-patterns/refs/anti-patterns-operational.md +216 -0
- package/skills/agentic/agentic-patterns/refs/pattern-catalog.md +329 -0
- package/skills/agentic/context-engineering/SKILL.md +142 -0
- package/skills/agentic/context-engineering/refs/caching-and-optimization.md +251 -0
- package/skills/agentic/context-engineering/refs/compression-techniques.md +171 -0
- package/skills/agentic/context-engineering/refs/cost-calculation-budget.md +250 -0
- package/skills/agentic/context-engineering/refs/cost-optimization-reporting.md +300 -0
- package/skills/agentic/context-engineering/refs/selective-loading.md +179 -0
- package/skills/agentic/frameworks/SKILL.md +191 -0
- package/skills/agentic/frameworks/refs/framework-profiles-1.md +209 -0
- package/skills/agentic/frameworks/refs/framework-profiles-2.md +214 -0
- package/skills/agentic/frameworks/refs/migration-patterns-paths.md +267 -0
- package/skills/agentic/frameworks/refs/migration-patterns-testing.md +208 -0
- package/skills/agentic/refs/audit.md +134 -0
- package/skills/agentic/refs/design.md +137 -0
- package/skills/agentic/refs/frameworks.md +102 -0
- package/skills/agentic/refs/review.md +160 -0
- package/skills/agentic/review-methodology/SKILL.md +186 -0
- package/skills/agentic/review-methodology/refs/deliverable-templates.md +246 -0
- package/skills/agentic/review-methodology/refs/issue-taxonomy-quality-testing.md +277 -0
- package/skills/agentic/review-methodology/refs/issue-taxonomy-reliability-safety.md +253 -0
- package/skills/agentic/trust-and-safety/SKILL.md +177 -0
- package/skills/agentic/trust-and-safety/refs/guardrails-actions.md +246 -0
- package/skills/agentic/trust-and-safety/refs/guardrails-input-output.md +238 -0
- package/skills/agentic/trust-and-safety/refs/guardrails-resources.md +209 -0
- package/skills/agentic/trust-and-safety/refs/safety-checklist-advanced.md +209 -0
- package/skills/agentic/trust-and-safety/refs/safety-checklist-core.md +215 -0
- package/skills/archetype/SKILL.md +104 -0
- package/skills/archetype/refs/build.md +142 -0
- package/skills/archetype/refs/decide.md +117 -0
- package/skills/archetype/refs/explore.md +66 -0
- package/skills/archetype/refs/incident.md +149 -0
- package/skills/archetype/refs/migrate.md +170 -0
- package/skills/archetype/refs/modernize.md +187 -0
- package/skills/archetype/refs/review.md +145 -0
- package/skills/archetype/refs/ship.md +117 -0
- package/skills/archetype/refs/specify.md +108 -0
- package/skills/archetype/refs/triage.md +62 -0
- package/skills/classify/SKILL.md +157 -0
- package/skills/data/analysis/SKILL.md +125 -0
- package/skills/data/analysis/refs/templates.md +170 -0
- package/skills/data/data/SKILL.md +118 -0
- package/skills/data/data/refs/examples.md +235 -0
- package/skills/data/ml/SKILL.md +125 -0
- package/skills/data/ml/refs/templates.md +172 -0
- package/skills/data/pipeline/SKILL.md +136 -0
- package/skills/data/pipeline/refs/templates.md +175 -0
- package/skills/data/refs/analyze.md +123 -0
- package/skills/data/refs/data.md +95 -0
- package/skills/data/refs/ml.md +118 -0
- package/skills/data/refs/pipeline.md +92 -0
- package/skills/deliberate/SKILL.md +125 -0
- package/skills/deliberate/refs/architecture-lens.md +37 -0
- package/skills/deliberate/refs/assumptions-lens.md +43 -0
- package/skills/deliberate/refs/code-lens.md +38 -0
- package/skills/deliberate/refs/content-lens.md +37 -0
- package/skills/deliberate/refs/data-lens.md +43 -0
- package/skills/deliberate/refs/design-lens.md +37 -0
- package/skills/deliberate/refs/opportunity-patterns.md +107 -0
- package/skills/deliberate/refs/ops-lens.md +43 -0
- package/skills/deliberate/refs/product-lens.md +46 -0
- package/skills/deliberate/refs/rethink-framework.md +77 -0
- package/skills/deliberate/refs/security-lens.md +47 -0
- package/skills/deliberate/refs/testing-lens.md +45 -0
- package/skills/deliberate/refs/timing-lens.md +42 -0
- package/skills/engineering/architecture/SKILL.md +177 -0
- package/skills/engineering/architecture/refs/adr-template.md +268 -0
- package/skills/engineering/architecture/refs/architecture-template-deployment.md +176 -0
- package/skills/engineering/architecture/refs/architecture-template-design.md +300 -0
- package/skills/engineering/architecture/refs/examples-ecommerce-analytics.md +299 -0
- package/skills/engineering/architecture/refs/examples-saas-trading.md +291 -0
- package/skills/engineering/architecture/refs/patterns-advanced.md +238 -0
- package/skills/engineering/architecture/refs/patterns-structural.md +303 -0
- package/skills/engineering/backend/SKILL.md +102 -0
- package/skills/engineering/backend/refs/checklists.md +146 -0
- package/skills/engineering/backend/refs/patterns.md +181 -0
- package/skills/engineering/debugging/SKILL.md +99 -0
- package/skills/engineering/debugging/refs/patterns.md +248 -0
- package/skills/engineering/debugging/refs/process.md +203 -0
- package/skills/engineering/docs/SKILL.md +97 -0
- package/skills/engineering/engineering/SKILL.md +88 -0
- package/skills/engineering/engineering/refs/checklists.md +91 -0
- package/skills/engineering/engineering/refs/templates.md +71 -0
- package/skills/engineering/frontend/SKILL.md +92 -0
- package/skills/engineering/frontend/refs/checklists.md +96 -0
- package/skills/engineering/frontend/refs/patterns.md +167 -0
- package/skills/engineering/integration/SKILL.md +183 -0
- package/skills/engineering/integration/refs/error-handling-best-practices.md +139 -0
- package/skills/engineering/integration/refs/error-handling-error-classes-typescript.md +212 -0
- package/skills/engineering/integration/refs/error-handling-error-response-format.md +301 -0
- package/skills/engineering/integration/refs/error-handling-retry-strategies.md +190 -0
- package/skills/engineering/integration/refs/event-schemas-best-practices.md +225 -0
- package/skills/engineering/integration/refs/event-schemas-event-naming-conventions.md +303 -0
- package/skills/engineering/integration/refs/event-schemas-event-structure.md +288 -0
- package/skills/engineering/integration/refs/graphql-best-practices.md +138 -0
- package/skills/engineering/integration/refs/graphql-error-handling.md +198 -0
- package/skills/engineering/integration/refs/graphql-graphql-basics.md +197 -0
- package/skills/engineering/integration/refs/graphql-query-examples.md +226 -0
- package/skills/engineering/integration/refs/graphql-schema-design-patterns.md +280 -0
- package/skills/engineering/integration/refs/grpc-grpc-overview.md +246 -0
- package/skills/engineering/integration/refs/grpc-implementation-examples.md +269 -0
- package/skills/engineering/integration/refs/grpc-metadata-headers.md +304 -0
- package/skills/engineering/integration/refs/grpc-testing.md +49 -0
- package/skills/engineering/integration/refs/openapi-template.yaml +682 -0
- package/skills/engineering/integration/refs/resilience-best-practices.md +109 -0
- package/skills/engineering/integration/refs/resilience-circuit-breaker-pattern.md +302 -0
- package/skills/engineering/integration/refs/resilience-rate-limiting.md +245 -0
- package/skills/engineering/integration/refs/resilience-timeout-pattern.md +212 -0
- package/skills/engineering/integration/refs/rest-api-fundamentals.md +299 -0
- package/skills/engineering/integration/refs/rest-api-responses-security.md +302 -0
- package/skills/engineering/integration/refs/versioning-breaking-changes.md +237 -0
- package/skills/engineering/integration/refs/versioning-migration-strategies.md +257 -0
- package/skills/engineering/integration/refs/versioning-versioning-strategies.md +296 -0
- package/skills/engineering/large-scale-migration/SKILL.md +65 -0
- package/skills/engineering/patch/SKILL.md +184 -0
- package/skills/engineering/refs/arch.md +126 -0
- package/skills/engineering/refs/debug.md +142 -0
- package/skills/engineering/refs/docs.md +190 -0
- package/skills/engineering/refs/plan.md +109 -0
- package/skills/engineering/refs/review.md +138 -0
- package/skills/engineering/system-design/SKILL.md +154 -0
- package/skills/engineering/system-design/refs/anti-patterns-big-ball-of-mud.md +254 -0
- package/skills/engineering/system-design/refs/anti-patterns-circular-dependencies.md +241 -0
- package/skills/engineering/system-design/refs/anti-patterns-feature-envy.md +168 -0
- package/skills/engineering/system-design/refs/anti-patterns-god-object.md +247 -0
- package/skills/engineering/system-design/refs/component-template-lifecycle.md +210 -0
- package/skills/engineering/system-design/refs/component-template-maintenance.md +219 -0
- package/skills/engineering/system-design/refs/component-template-structure.md +276 -0
- package/skills/engineering/system-design/refs/dependencies-best-practices.md +260 -0
- package/skills/engineering/system-design/refs/dependencies-dependency-principles.md +295 -0
- package/skills/engineering/system-design/refs/dependencies-dependency-tracking.md +261 -0
- package/skills/engineering/system-design/refs/interface-template-lifecycle.md +211 -0
- package/skills/engineering/system-design/refs/interface-template-maintenance.md +212 -0
- package/skills/engineering/system-design/refs/interface-template-structure.md +269 -0
- package/skills/engineering/system-design/refs/patterns-dependency-injection.md +151 -0
- package/skills/engineering/system-design/refs/patterns-facade-pattern.md +257 -0
- package/skills/engineering/system-design/refs/patterns-layered-pattern.md +204 -0
- package/skills/engineering/system-design/refs/patterns-plugin-architecture.md +229 -0
- package/skills/engineering/unit-test-quality/SKILL.md +194 -0
- package/skills/ground/SKILL.md +130 -0
- package/skills/integration-discovery/SKILL.md +168 -0
- package/skills/integration-discovery/refs/capabilities.md +282 -0
- package/skills/integration-discovery/refs/cli-detection.md +295 -0
- package/skills/integration-discovery/refs/discovery-sources.md +233 -0
- package/skills/integration-discovery/refs/task-patterns.md +206 -0
- package/skills/jam/SKILL.md +45 -0
- package/skills/jam/refs/facilitation-patterns.md +125 -0
- package/skills/jam/refs/quick.md +64 -0
- package/skills/jam/refs/synthesis-patterns.md +114 -0
- package/skills/multi-model/SKILL.md +168 -0
- package/skills/multi-model/refs/aichat.md +119 -0
- package/skills/multi-model/refs/aider.md +100 -0
- package/skills/multi-model/refs/auditability.md +238 -0
- package/skills/multi-model/refs/codex.md +169 -0
- package/skills/multi-model/refs/context.md +306 -0
- package/skills/multi-model/refs/copilot.md +161 -0
- package/skills/multi-model/refs/examples.md +224 -0
- package/skills/multi-model/refs/gemini.md +185 -0
- package/skills/multi-model/refs/goose.md +112 -0
- package/skills/multi-model/refs/llm.md +124 -0
- package/skills/multi-model/refs/opencode.md +196 -0
- package/skills/multi-model/refs/orchestration.md +188 -0
- package/skills/multi-model/refs/pi.md +208 -0
- package/skills/persona/SKILL.md +144 -0
- package/skills/persona/refs/define.md +133 -0
- package/skills/platform/actions/refs/actions.md +114 -0
- package/skills/platform/audit/SKILL.md +174 -0
- package/skills/platform/audit/refs/audit.md +145 -0
- package/skills/platform/audit/refs/checklists-evidence-operations.md +144 -0
- package/skills/platform/audit/refs/checklists-gdpr-pci-evidence.md +213 -0
- package/skills/platform/audit/refs/checklists-soc2-hipaa.md +120 -0
- package/skills/platform/audit/refs/frameworks-gdpr-pci.md +225 -0
- package/skills/platform/audit/refs/frameworks-soc2-hipaa.md +228 -0
- package/skills/platform/compliance/SKILL.md +169 -0
- package/skills/platform/compliance/refs/checklists.md +303 -0
- package/skills/platform/compliance/refs/compliance.md +117 -0
- package/skills/platform/compliance/refs/frameworks.md +282 -0
- package/skills/platform/errors/SKILL.md +183 -0
- package/skills/platform/errors/refs/patterns.md +271 -0
- package/skills/platform/errors/refs/severity.md +264 -0
- package/skills/platform/gate-benchmark-rebaseline/SKILL.md +108 -0
- package/skills/platform/gh/refs/gh.md +105 -0
- package/skills/platform/gh-cli/SKILL.md +120 -0
- package/skills/platform/gh-cli/refs/automation.md +63 -0
- package/skills/platform/gh-cli/refs/gh-ops.md +103 -0
- package/skills/platform/gh-cli/refs/patterns.md +132 -0
- package/skills/platform/gh-cli/scripts/gh_ops.py +454 -0
- package/skills/platform/github-actions/SKILL.md +159 -0
- package/skills/platform/github-actions/refs/security.md +150 -0
- package/skills/platform/github-actions/refs/templates.md +230 -0
- package/skills/platform/github-actions/refs/troubleshooting.md +174 -0
- package/skills/platform/github-actions/scripts/workflow_gen.py +215 -0
- package/skills/platform/gitlab-ci/SKILL.md +140 -0
- package/skills/platform/gitlab-ci/refs/templates.md +223 -0
- package/skills/platform/gitlab-ci/refs/troubleshooting.md +213 -0
- package/skills/platform/glab-cli/SKILL.md +133 -0
- package/skills/platform/glab-cli/refs/ci-debugging.md +95 -0
- package/skills/platform/glab-cli/refs/glab-ops.md +78 -0
- package/skills/platform/glab-cli/refs/patterns.md +131 -0
- package/skills/platform/glab-cli/scripts/glab_ops.py +313 -0
- package/skills/platform/health/SKILL.md +177 -0
- package/skills/platform/health/refs/health.md +72 -0
- package/skills/platform/health/refs/sources.md +302 -0
- package/skills/platform/incident/refs/incident.md +136 -0
- package/skills/platform/infra/refs/infra.md +104 -0
- package/skills/platform/observability/SKILL.md +128 -0
- package/skills/platform/observability/refs/toolchain-discovery.md +243 -0
- package/skills/platform/prereq-doctor/SKILL.md +57 -0
- package/skills/platform/prereq-doctor/refs/tool-registry.md +58 -0
- package/skills/platform/traces/refs/traces.md +101 -0
- package/skills/product/acceptance-criteria/SKILL.md +193 -0
- package/skills/product/acceptance-criteria/refs/ac-anti-patterns.md +291 -0
- package/skills/product/acceptance-criteria/refs/ac-examples.md +277 -0
- package/skills/product/accessibility/SKILL.md +197 -0
- package/skills/product/accessibility/refs/aria-patterns-basics.md +250 -0
- package/skills/product/accessibility/refs/aria-patterns-dynamic.md +187 -0
- package/skills/product/accessibility/refs/aria-patterns-interactive.md +246 -0
- package/skills/product/accessibility/refs/audit-report-findings.md +248 -0
- package/skills/product/accessibility/refs/audit-report-results.md +276 -0
- package/skills/product/accessibility/refs/common-violations-html-css.md +270 -0
- package/skills/product/accessibility/refs/common-violations-interactive.md +303 -0
- package/skills/product/accessibility/refs/keyboard-testing-basics.md +222 -0
- package/skills/product/accessibility/refs/keyboard-testing-patterns.md +173 -0
- package/skills/product/accessibility/refs/screen-reader-testing-advanced.md +294 -0
- package/skills/product/accessibility/refs/screen-reader-testing-commands.md +255 -0
- package/skills/product/accessibility/refs/wcag-checklist.md +262 -0
- package/skills/product/analyze/SKILL.md +164 -0
- package/skills/product/analyze/refs/algorithms.md +238 -0
- package/skills/product/analyze/refs/sentiment-patterns.md +180 -0
- package/skills/product/imagery/SKILL.md +97 -0
- package/skills/product/imagery/alter/SKILL.md +105 -0
- package/skills/product/imagery/alter/refs/editing-reference.md +146 -0
- package/skills/product/imagery/create/SKILL.md +109 -0
- package/skills/product/imagery/create/refs/prompt-engineering.md +112 -0
- package/skills/product/imagery/create/refs/provider-reference.md +219 -0
- package/skills/product/imagery/review/SKILL.md +101 -0
- package/skills/product/imagery/review/refs/analysis-lenses.md +136 -0
- package/skills/product/imagery/review/refs/quality-gates.md +153 -0
- package/skills/product/imagery/scripts/analyze.sh +23 -0
- package/skills/product/imagery/scripts/edit.sh +14 -0
- package/skills/product/imagery/scripts/generate.sh +13 -0
- package/skills/product/imagery/scripts/provider.py +787 -0
- package/skills/product/listen/SKILL.md +175 -0
- package/skills/product/listen/refs/channels.md +220 -0
- package/skills/product/mockup/SKILL.md +106 -0
- package/skills/product/mockup/refs/templates.md +95 -0
- package/skills/product/refs/a11y.md +109 -0
- package/skills/product/refs/acceptance.md +79 -0
- package/skills/product/refs/align.md +67 -0
- package/skills/product/refs/analyze.md +77 -0
- package/skills/product/refs/elicit.md +67 -0
- package/skills/product/refs/listen.md +58 -0
- package/skills/product/refs/mockup.md +77 -0
- package/skills/product/refs/screenshot.md +59 -0
- package/skills/product/refs/strategy.md +77 -0
- package/skills/product/refs/synthesize.md +54 -0
- package/skills/product/refs/ux-review.md +68 -0
- package/skills/product/refs/ux.md +101 -0
- package/skills/product/requirements-analysis/SKILL.md +136 -0
- package/skills/product/requirements-analysis/refs/requirements-example-auth.md +264 -0
- package/skills/product/requirements-analysis/refs/requirements-example-export-integration.md +88 -0
- package/skills/product/requirements-analysis/refs/requirements-output-format-template.md +247 -0
- package/skills/product/requirements-analysis/refs/user-story-guide.md +296 -0
- package/skills/product/requirements-graph/SKILL.md +155 -0
- package/skills/product/requirements-graph/refs/examples.md +223 -0
- package/skills/product/requirements-graph/refs/schema.md +162 -0
- package/skills/product/requirements-migrate/SKILL.md +90 -0
- package/skills/product/requirements-navigate/SKILL.md +141 -0
- package/skills/product/requirements-navigate/refs/meta-templates.md +141 -0
- package/skills/product/screenshot/SKILL.md +147 -0
- package/skills/product/strategy/SKILL.md +198 -0
- package/skills/product/strategy/refs/frameworks.md +295 -0
- package/skills/product/strategy/refs/templates-competitive-market.md +299 -0
- package/skills/product/strategy/refs/templates-roi-value.md +207 -0
- package/skills/product/synthesize/SKILL.md +116 -0
- package/skills/product/synthesize/refs/journey-mapping.md +212 -0
- package/skills/product/synthesize/refs/prioritization.md +193 -0
- package/skills/product/ux-review/SKILL.md +164 -0
- package/skills/product/visual-direction/SKILL.md +137 -0
- package/skills/product/visual-review/SKILL.md +131 -0
- package/skills/runtime-exec/SKILL.md +138 -0
- package/skills/search/codebase-narrator/SKILL.md +131 -0
- package/skills/search/codebase-narrator/refs/output-template.md +100 -0
- package/skills/smaht/SKILL.md +72 -0
- package/skills/smaht/discovery/SKILL.md +65 -0
- package/skills/smaht/intent/SKILL.md +89 -0
- package/skills/smaht/propose-skills/SKILL.md +142 -0
- package/skills/smaht/refs/state.md +76 -0
- package/skills/swarm/SKILL.md +132 -0
- package/skills/swarm/refs/fan-out.md +104 -0
- package/skills/swarm/refs/independent-verification.md +86 -0
- package/skills/swarm/refs/receipts-and-evidence.md +69 -0
- package/skills/swarm/refs/recon-synthesis.md +87 -0
- package/skills/swarm/refs/ship-discipline.md +90 -0
- package/skills/wickedizer/SKILL.md +147 -0
- package/skills/wickedizer/refs/artifact-types.md +238 -0
- package/skills/wickedizer/refs/complexity.md +278 -0
- package/skills/wickedizer/refs/de-ai-pass.md +140 -0
- package/skills/wickedizer/refs/failure-modes.md +249 -0
- package/skills/wickedizer/refs/patterns.md +282 -0
- package/skills/wickedizer/refs/review.md +221 -0
- package/skills/wickedizer/refs/structure.md +282 -0
- package/skills/wickedizer/refs/voice-profile.md +125 -0
- package/skills/workflow/SKILL.md +132 -0
- package/skills/workflow/refs/archetype-adjustments.md +205 -0
- package/skills/workflow/refs/evidence.md +58 -0
- package/skills/workflow/refs/integration.md +130 -0
- package/skills/workflow/refs/risk-dimension-signals.md +260 -0
- package/skills/workflow/refs/scoring-rubric.md +49 -0
- package/skills/workflow/refs/signal-keywords.md +176 -0
- package/skills/workflow/refs/specialist-routing-rules.md +159 -0
- package/skills/worktrees/SKILL.md +87 -0
- package/skills/worktrees/refs/recipes.md +96 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Brain adapter for wicked-smaht context assembly.
|
|
3
|
+
|
|
4
|
+
Queries the wicked-brain FTS5 index for code and document context
|
|
5
|
+
relevant to the current prompt. Returns ContextItems tagged with
|
|
6
|
+
source="brain" so the slow path briefing formatter labels them correctly.
|
|
7
|
+
|
|
8
|
+
wicked-brain is a required dependency — context assembly is degraded without it.
|
|
9
|
+
When brain is unreachable, this adapter logs a warning to stderr and returns empty.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
import urllib.error
|
|
16
|
+
import urllib.request
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import List
|
|
19
|
+
|
|
20
|
+
from . import ContextItem, run_in_thread
|
|
21
|
+
|
|
22
|
+
_STOP_WORDS = frozenset({
|
|
23
|
+
"the", "a", "an", "is", "are", "was", "were", "be", "been", "have", "has",
|
|
24
|
+
"had", "do", "does", "did", "will", "would", "could", "should", "can",
|
|
25
|
+
"may", "might", "must", "i", "you", "we", "they", "me", "my", "your",
|
|
26
|
+
"this", "that", "these", "those", "what", "which", "who", "how", "why",
|
|
27
|
+
"when", "where", "and", "or", "but", "if", "for", "of", "to", "from",
|
|
28
|
+
"in", "on", "at", "by", "with", "about", "not", "so", "just", "also",
|
|
29
|
+
"need", "want", "let", "get", "make", "test", "check", "fix", "work",
|
|
30
|
+
# English filler that passes len>2 but over-constrains FTS5 AND matching
|
|
31
|
+
"one", "two", "all", "any", "some", "out", "use", "via", "per",
|
|
32
|
+
"without", "going", "through", "using", "into", "onto", "upon",
|
|
33
|
+
"there", "their", "then", "than", "its", "our", "has",
|
|
34
|
+
# Prepositions / general connectors that look content-y but aren't
|
|
35
|
+
"between", "across", "along", "around", "before", "after",
|
|
36
|
+
"exist", "exists", "show", "tell", "give", "take",
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _extract_keywords(prompt: str, limit: int = 3) -> str:
|
|
41
|
+
"""Extract up to `limit` keywords for FTS5 AND query.
|
|
42
|
+
|
|
43
|
+
Position-order preserves the prompt's intent; the first non-stop words
|
|
44
|
+
are almost always the topic. Callers pass limit=2 for retry fallback.
|
|
45
|
+
"""
|
|
46
|
+
words = prompt.lower().split()
|
|
47
|
+
keywords = [w for w in words if w not in _STOP_WORDS and len(w) > 2]
|
|
48
|
+
seen: set[str] = set()
|
|
49
|
+
unique = []
|
|
50
|
+
for w in keywords:
|
|
51
|
+
if w not in seen:
|
|
52
|
+
seen.add(w)
|
|
53
|
+
unique.append(w)
|
|
54
|
+
return " ".join(unique[:limit]) if unique else ""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _query_brain(prompt: str) -> list:
|
|
58
|
+
"""Query brain FTS5 index with automatic recall fallback.
|
|
59
|
+
|
|
60
|
+
FTS5 uses AND — more terms = fewer results. Try 3 terms first (higher
|
|
61
|
+
precision); if < 2 results, try two 2-term combinations and pick the
|
|
62
|
+
one with more results:
|
|
63
|
+
- first + third (drop middle — often the most generic term)
|
|
64
|
+
- first + second (standard narrowing)
|
|
65
|
+
"""
|
|
66
|
+
keywords = _extract_keywords(prompt, limit=3).split()
|
|
67
|
+
if not keywords:
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
query = " ".join(keywords)
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
from _brain_port import resolve_port as _resolve_port
|
|
74
|
+
port = _resolve_port()
|
|
75
|
+
|
|
76
|
+
def _search(q: str) -> list:
|
|
77
|
+
payload = json.dumps({
|
|
78
|
+
"action": "search",
|
|
79
|
+
"params": {"query": q, "limit": 10},
|
|
80
|
+
}).encode("utf-8")
|
|
81
|
+
req = urllib.request.Request(
|
|
82
|
+
f"http://localhost:{port}/api",
|
|
83
|
+
data=payload,
|
|
84
|
+
headers={"Content-Type": "application/json"},
|
|
85
|
+
method="POST",
|
|
86
|
+
)
|
|
87
|
+
with urllib.request.urlopen(req, timeout=3) as resp:
|
|
88
|
+
return json.loads(resp.read().decode("utf-8")).get("results", [])
|
|
89
|
+
|
|
90
|
+
results = _search(query)
|
|
91
|
+
if len(results) < 2 and len(keywords) >= 3:
|
|
92
|
+
# Try dropping the middle keyword (often the least specific)
|
|
93
|
+
alt_a = f"{keywords[0]} {keywords[2]}" # first + third
|
|
94
|
+
alt_b = f"{keywords[0]} {keywords[1]}" # first + second
|
|
95
|
+
ra = _search(alt_a)
|
|
96
|
+
rb = _search(alt_b)
|
|
97
|
+
# Prefer whichever returns more results (wider recall)
|
|
98
|
+
results = ra if len(ra) >= len(rb) else rb
|
|
99
|
+
elif len(results) < 2 and len(keywords) == 2:
|
|
100
|
+
# Already at 2 terms; nothing further to try
|
|
101
|
+
pass # intentional: no-op
|
|
102
|
+
return results
|
|
103
|
+
except Exception as _e:
|
|
104
|
+
print(
|
|
105
|
+
f"smaht: brain adapter unreachable (port {port})"
|
|
106
|
+
f" — context assembly degraded: {type(_e).__name__}",
|
|
107
|
+
file=sys.stderr,
|
|
108
|
+
)
|
|
109
|
+
return []
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _keyword_score(prompt_lower: str, text: str) -> float:
|
|
113
|
+
"""Score text by keyword overlap with prompt."""
|
|
114
|
+
if not text:
|
|
115
|
+
return 0.0
|
|
116
|
+
text_lower = text.lower()
|
|
117
|
+
score = 0.0
|
|
118
|
+
for word in prompt_lower.split():
|
|
119
|
+
if len(word) > 3 and word in text_lower:
|
|
120
|
+
score += 0.15
|
|
121
|
+
return min(score, 0.45)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _readable_title(source_file: str) -> str:
|
|
125
|
+
"""Convert a chunk source path to a human-readable title.
|
|
126
|
+
|
|
127
|
+
e.g. "skills-crew-workflow-refs-specialist-routing-rules.md"
|
|
128
|
+
→ "crew / specialist-routing-rules"
|
|
129
|
+
"""
|
|
130
|
+
import re as _re
|
|
131
|
+
# Strip leading domain prefix like "skills-", "commands-", "agents-", "hooks-"
|
|
132
|
+
name = _re.sub(r'^(skills|commands|agents|hooks|scenarios|scripts|docs)-', '', source_file)
|
|
133
|
+
# Strip .md extension
|
|
134
|
+
name = name.removesuffix('.md')
|
|
135
|
+
# Split on '-' to get components; find the domain and the tail
|
|
136
|
+
parts = name.split('-')
|
|
137
|
+
if len(parts) >= 2:
|
|
138
|
+
# First part is domain; rest is description
|
|
139
|
+
domain = parts[0]
|
|
140
|
+
# Skip "refs" and numeric-looking chunks
|
|
141
|
+
desc_parts = [p for p in parts[1:] if p != 'refs' and not p.startswith('chunk')]
|
|
142
|
+
if desc_parts:
|
|
143
|
+
return f"{domain} / {'-'.join(desc_parts)}"
|
|
144
|
+
return name
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _clean_snippet(raw: str) -> str:
|
|
148
|
+
"""Strip YAML frontmatter lines and FTS highlight tags from snippet.
|
|
149
|
+
|
|
150
|
+
FTS5 snippets contain frontmatter when the brain server re-indexes full
|
|
151
|
+
chunk files. Strip aggressively: snake_case keys, floats, timestamps,
|
|
152
|
+
list tags, and separator markers.
|
|
153
|
+
"""
|
|
154
|
+
import re as _re
|
|
155
|
+
|
|
156
|
+
# Remove FTS5 highlight markers and ellipsis separators
|
|
157
|
+
text = _re.sub(r"<[^>]+>", "", raw)
|
|
158
|
+
text = text.replace("…", " ").replace("...", " ")
|
|
159
|
+
|
|
160
|
+
# Patterns that indicate frontmatter / metadata noise — skip these lines
|
|
161
|
+
_yaml_key = _re.compile(r'^[a-z][a-z_]+:\s*') # snake_case key: value
|
|
162
|
+
_bare_float = _re.compile(r'^\d+\.\d+$') # e.g. "0.7"
|
|
163
|
+
_timestamp = _re.compile(r'^\d{4}-\d{2}-\d{2}') # ISO date
|
|
164
|
+
_tag_list = _re.compile(r'^- [a-z][\w\-]*$') # bare YAML tag list items
|
|
165
|
+
_flag_list = _re.compile(r'^- --[\w\-]+') # CLI flag list items: - --flag
|
|
166
|
+
_uuid_like = _re.compile(r'^[a-f0-9\-]{8,}$') # UUIDs
|
|
167
|
+
# Leftover path values after their YAML key was stripped
|
|
168
|
+
_file_path = _re.compile(r'^[\w/.\- ]+\.(md|py|js|ts|jsx|tsx|json|yaml|yml|sh|txt)$')
|
|
169
|
+
# chunk-ID paths: "source-name/chunk-NNN" or bare "chunk-NNN"
|
|
170
|
+
_chunk_id = _re.compile(r'(^|/)chunk-\d+')
|
|
171
|
+
# Markdown table rows: any line starting with | (data rows and separators)
|
|
172
|
+
_table_row = _re.compile(r'^\|')
|
|
173
|
+
|
|
174
|
+
lines = []
|
|
175
|
+
for line in text.split("\n"):
|
|
176
|
+
stripped = line.strip()
|
|
177
|
+
if not stripped or stripped == "---":
|
|
178
|
+
continue
|
|
179
|
+
if (_yaml_key.match(stripped)
|
|
180
|
+
or _bare_float.match(stripped)
|
|
181
|
+
or _timestamp.match(stripped)
|
|
182
|
+
or _tag_list.match(stripped)
|
|
183
|
+
or _flag_list.match(stripped)
|
|
184
|
+
or _uuid_like.match(stripped)
|
|
185
|
+
or _file_path.match(stripped)
|
|
186
|
+
or _chunk_id.search(stripped)
|
|
187
|
+
or _table_row.match(stripped)):
|
|
188
|
+
continue
|
|
189
|
+
lines.append(stripped)
|
|
190
|
+
|
|
191
|
+
result = " ".join(lines).strip()
|
|
192
|
+
return result[:160] if result else ""
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
async def query(prompt: str) -> List[ContextItem]:
|
|
196
|
+
"""Query brain for code and document context relevant to the prompt."""
|
|
197
|
+
results = await run_in_thread(_query_brain, prompt)
|
|
198
|
+
if not results:
|
|
199
|
+
return []
|
|
200
|
+
|
|
201
|
+
import re
|
|
202
|
+
# Score against extracted keywords only (not full prompt) so incidental
|
|
203
|
+
# words in the prompt (e.g. "crew" in "without going through the crew
|
|
204
|
+
# workflow") don't boost unrelated documents that happen to mention them.
|
|
205
|
+
score_against = _extract_keywords(prompt, limit=3) or prompt.lower()
|
|
206
|
+
|
|
207
|
+
# First pass: build items grouped by source file (deduplicate chunks → 1 item per source)
|
|
208
|
+
best_by_source: dict[str, dict] = {}
|
|
209
|
+
|
|
210
|
+
for r in results:
|
|
211
|
+
path = r.get("path", "") or r.get("id", "")
|
|
212
|
+
snippet = r.get("snippet", "")
|
|
213
|
+
|
|
214
|
+
# Determine source file from chunk path
|
|
215
|
+
source_file = ""
|
|
216
|
+
if "chunks/extracted/" in path:
|
|
217
|
+
part = path.replace("chunks/extracted/", "").split("/chunk-")[0]
|
|
218
|
+
source_file = part
|
|
219
|
+
else:
|
|
220
|
+
source_file = path
|
|
221
|
+
|
|
222
|
+
clean_snippet = _clean_snippet(snippet)
|
|
223
|
+
kw_score = _keyword_score(score_against, f"{source_file} {clean_snippet}")
|
|
224
|
+
# Items with no readable snippet get a relevance floor of 0.2 so they
|
|
225
|
+
# rank below items that survived cleaning and only appear if budget allows.
|
|
226
|
+
base = 0.2 if not clean_snippet else 0.3
|
|
227
|
+
relevance = min(base + kw_score, 1.0)
|
|
228
|
+
|
|
229
|
+
# Keep only the highest-scoring chunk per source file
|
|
230
|
+
existing = best_by_source.get(source_file)
|
|
231
|
+
if existing is None or relevance > existing["relevance"]:
|
|
232
|
+
best_by_source[source_file] = {
|
|
233
|
+
"path": path,
|
|
234
|
+
"source_file": source_file,
|
|
235
|
+
"snippet": clean_snippet,
|
|
236
|
+
"relevance": relevance,
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
# Second pass: convert to ContextItems
|
|
240
|
+
items: List[ContextItem] = []
|
|
241
|
+
for source_file, entry in best_by_source.items():
|
|
242
|
+
title = _readable_title(source_file)
|
|
243
|
+
items.append(ContextItem(
|
|
244
|
+
id=entry["path"],
|
|
245
|
+
source="brain",
|
|
246
|
+
title=title,
|
|
247
|
+
summary=entry["snippet"],
|
|
248
|
+
excerpt=entry["snippet"][:100],
|
|
249
|
+
relevance=entry["relevance"],
|
|
250
|
+
metadata={"brain_path": entry["path"]},
|
|
251
|
+
))
|
|
252
|
+
|
|
253
|
+
items.sort(key=lambda x: x.relevance, reverse=True)
|
|
254
|
+
return items
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wicked-smaht adapter for Context7.
|
|
3
|
+
|
|
4
|
+
Queries external library documentation via Context7 MCP integration.
|
|
5
|
+
Provides graceful degradation when Context7 is unavailable.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import hashlib
|
|
10
|
+
import json
|
|
11
|
+
import sys
|
|
12
|
+
from datetime import datetime, timezone
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import List, Optional, Dict, Any
|
|
15
|
+
|
|
16
|
+
from . import ContextItem, _SCRIPTS_ROOT
|
|
17
|
+
|
|
18
|
+
if str(_SCRIPTS_ROOT) not in sys.path:
|
|
19
|
+
sys.path.insert(0, str(_SCRIPTS_ROOT))
|
|
20
|
+
|
|
21
|
+
from _domain_store import get_local_path
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Cache configuration
|
|
25
|
+
CACHE_DIR = get_local_path("wicked-smaht", "cache", "context7")
|
|
26
|
+
CACHE_TTL_SECONDS = 3600 # 1 hour
|
|
27
|
+
MAX_CACHE_ENTRIES = 500
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Context7Cache:
|
|
31
|
+
"""Simple file-based cache for Context7 query results."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, cache_dir: Path = CACHE_DIR):
|
|
34
|
+
self.cache_dir = cache_dir
|
|
35
|
+
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
self.index_path = cache_dir / "index.json"
|
|
37
|
+
self.data_dir = cache_dir / "data"
|
|
38
|
+
self.data_dir.mkdir(exist_ok=True)
|
|
39
|
+
self._load_index()
|
|
40
|
+
|
|
41
|
+
def _load_index(self):
|
|
42
|
+
"""Load cache index from disk."""
|
|
43
|
+
if self.index_path.exists():
|
|
44
|
+
try:
|
|
45
|
+
with open(self.index_path) as f:
|
|
46
|
+
self.index = json.load(f)
|
|
47
|
+
except Exception:
|
|
48
|
+
self.index = {}
|
|
49
|
+
else:
|
|
50
|
+
self.index = {}
|
|
51
|
+
|
|
52
|
+
def _save_index(self):
|
|
53
|
+
"""Save cache index to disk."""
|
|
54
|
+
with open(self.index_path, 'w') as f:
|
|
55
|
+
json.dump(self.index, f, indent=2)
|
|
56
|
+
|
|
57
|
+
def _cache_key(self, library_id: str, query: str) -> str:
|
|
58
|
+
"""Generate cache key from library ID and query."""
|
|
59
|
+
content = f"{library_id}:{query}"
|
|
60
|
+
return hashlib.sha256(content.encode()).hexdigest()[:16]
|
|
61
|
+
|
|
62
|
+
def _is_valid(self, entry: Dict[str, Any]) -> bool:
|
|
63
|
+
"""Check if cache entry is still valid."""
|
|
64
|
+
cached_at = datetime.fromisoformat(entry['cached_at'])
|
|
65
|
+
age_seconds = (datetime.now(timezone.utc) - cached_at).total_seconds()
|
|
66
|
+
return age_seconds < CACHE_TTL_SECONDS
|
|
67
|
+
|
|
68
|
+
def get(self, library_id: str, query: str) -> Optional[List[ContextItem]]:
|
|
69
|
+
"""Get cached results if valid, None otherwise."""
|
|
70
|
+
key = self._cache_key(library_id, query)
|
|
71
|
+
|
|
72
|
+
# Check index
|
|
73
|
+
if key not in self.index:
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
entry = self.index[key]
|
|
77
|
+
|
|
78
|
+
# Validate TTL
|
|
79
|
+
if not self._is_valid(entry):
|
|
80
|
+
# Clean up expired entry
|
|
81
|
+
self._remove(key)
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
# Load data
|
|
85
|
+
data_path = self.data_dir / f"{key}.json"
|
|
86
|
+
if not data_path.exists():
|
|
87
|
+
# Index/data mismatch - clean up
|
|
88
|
+
self._remove(key)
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
with open(data_path) as f:
|
|
93
|
+
data = json.load(f)
|
|
94
|
+
|
|
95
|
+
# Reconstruct ContextItems
|
|
96
|
+
items = []
|
|
97
|
+
for item_data in data:
|
|
98
|
+
items.append(ContextItem(
|
|
99
|
+
id=item_data['id'],
|
|
100
|
+
source=item_data['source'],
|
|
101
|
+
title=item_data['title'],
|
|
102
|
+
summary=item_data['summary'],
|
|
103
|
+
excerpt=item_data.get('excerpt', ''),
|
|
104
|
+
relevance=item_data.get('relevance', 0.0),
|
|
105
|
+
age_days=item_data.get('age_days', 0.0),
|
|
106
|
+
metadata=item_data.get('metadata', {})
|
|
107
|
+
))
|
|
108
|
+
|
|
109
|
+
return items
|
|
110
|
+
except Exception as e:
|
|
111
|
+
print(f"Warning: Failed to load cache entry {key}: {e}", file=sys.stderr)
|
|
112
|
+
self._remove(key)
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
def set(self, library_id: str, query: str, items: List[ContextItem]):
|
|
116
|
+
"""Cache query results."""
|
|
117
|
+
key = self._cache_key(library_id, query)
|
|
118
|
+
|
|
119
|
+
# Serialize items
|
|
120
|
+
items_data = []
|
|
121
|
+
for item in items:
|
|
122
|
+
items_data.append({
|
|
123
|
+
'id': item.id,
|
|
124
|
+
'source': item.source,
|
|
125
|
+
'title': item.title,
|
|
126
|
+
'summary': item.summary,
|
|
127
|
+
'excerpt': item.excerpt,
|
|
128
|
+
'relevance': item.relevance,
|
|
129
|
+
'age_days': item.age_days,
|
|
130
|
+
'metadata': item.metadata
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
# Write data
|
|
134
|
+
data_path = self.data_dir / f"{key}.json"
|
|
135
|
+
with open(data_path, 'w') as f:
|
|
136
|
+
json.dump(items_data, f, indent=2)
|
|
137
|
+
|
|
138
|
+
# Update index
|
|
139
|
+
self.index[key] = {
|
|
140
|
+
'library_id': library_id,
|
|
141
|
+
'query': query,
|
|
142
|
+
'cached_at': datetime.now(timezone.utc).isoformat(),
|
|
143
|
+
'item_count': len(items)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Enforce max entries (LRU-style cleanup)
|
|
147
|
+
if len(self.index) > MAX_CACHE_ENTRIES:
|
|
148
|
+
self._evict_oldest()
|
|
149
|
+
|
|
150
|
+
self._save_index()
|
|
151
|
+
|
|
152
|
+
def _remove(self, key: str):
|
|
153
|
+
"""Remove cache entry."""
|
|
154
|
+
# Remove from index
|
|
155
|
+
if key in self.index:
|
|
156
|
+
del self.index[key]
|
|
157
|
+
self._save_index()
|
|
158
|
+
|
|
159
|
+
# Remove data file
|
|
160
|
+
data_path = self.data_dir / f"{key}.json"
|
|
161
|
+
if data_path.exists():
|
|
162
|
+
data_path.unlink()
|
|
163
|
+
|
|
164
|
+
def _evict_oldest(self):
|
|
165
|
+
"""Evict oldest 10% of entries."""
|
|
166
|
+
# Sort by cached_at
|
|
167
|
+
sorted_entries = sorted(
|
|
168
|
+
self.index.items(),
|
|
169
|
+
key=lambda x: x[1]['cached_at']
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
evict_count = max(1, len(sorted_entries) // 10)
|
|
173
|
+
for key, _ in sorted_entries[:evict_count]:
|
|
174
|
+
self._remove(key)
|
|
175
|
+
|
|
176
|
+
def clear(self):
|
|
177
|
+
"""Clear entire cache."""
|
|
178
|
+
for key in list(self.index.keys()):
|
|
179
|
+
self._remove(key)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# Global cache instance
|
|
183
|
+
_cache = Context7Cache()
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
async def query(prompt: str, project: str = None) -> List[ContextItem]:
|
|
187
|
+
"""
|
|
188
|
+
Query Context7 for relevant library documentation.
|
|
189
|
+
|
|
190
|
+
This adapter uses the Context7 MCP integration to fetch external library docs.
|
|
191
|
+
|
|
192
|
+
Strategy:
|
|
193
|
+
1. Extract library names from prompt
|
|
194
|
+
2. Check local cheatsheet store (hot tier — no MCP call needed)
|
|
195
|
+
3. Resolve library IDs via Context7 (cached) for misses
|
|
196
|
+
4. Query documentation (cached)
|
|
197
|
+
5. Transform to ContextItems
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
prompt: User's query/prompt
|
|
201
|
+
project: Optional project context (unused for Context7)
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
List of ContextItems with documentation snippets
|
|
205
|
+
"""
|
|
206
|
+
items = []
|
|
207
|
+
|
|
208
|
+
# Extract potential library names from prompt
|
|
209
|
+
library_names = _extract_library_names(prompt)
|
|
210
|
+
if not library_names:
|
|
211
|
+
return items
|
|
212
|
+
|
|
213
|
+
# For each library, try to get docs
|
|
214
|
+
for lib_name in library_names[:3]: # Limit to 3 libraries
|
|
215
|
+
try:
|
|
216
|
+
# Try to get from cache first
|
|
217
|
+
cached = _cache.get(lib_name, prompt)
|
|
218
|
+
if cached is not None:
|
|
219
|
+
items.extend(cached)
|
|
220
|
+
continue
|
|
221
|
+
|
|
222
|
+
# Not cached - query Context7
|
|
223
|
+
lib_items = await _query_context7(lib_name, prompt)
|
|
224
|
+
|
|
225
|
+
# Cache results (even if empty)
|
|
226
|
+
_cache.set(lib_name, prompt, lib_items)
|
|
227
|
+
|
|
228
|
+
items.extend(lib_items)
|
|
229
|
+
|
|
230
|
+
except asyncio.TimeoutError:
|
|
231
|
+
print(f"Warning: Context7 query timeout for {lib_name}", file=sys.stderr)
|
|
232
|
+
except Exception as e:
|
|
233
|
+
print(f"Warning: Context7 query failed for {lib_name}: {e}", file=sys.stderr)
|
|
234
|
+
|
|
235
|
+
return items
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
async def _query_context7(library_name: str, query: str, timeout: float = 5.0) -> List[ContextItem]:
|
|
239
|
+
"""
|
|
240
|
+
Query Context7 for a specific library.
|
|
241
|
+
|
|
242
|
+
This function interfaces with the Context7 MCP tools if available.
|
|
243
|
+
Falls back gracefully if MCP integration is not present.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
library_name: Name of the library (e.g., "react", "express")
|
|
247
|
+
query: The user's query
|
|
248
|
+
timeout: Query timeout in seconds
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
List of ContextItems from Context7 docs
|
|
252
|
+
"""
|
|
253
|
+
items = []
|
|
254
|
+
|
|
255
|
+
# Check if Context7 MCP tools are available
|
|
256
|
+
try:
|
|
257
|
+
# Import at runtime to avoid hard dependency
|
|
258
|
+
# This would be the MCP integration point
|
|
259
|
+
# For now, we'll use a subprocess approach to call MCP tools
|
|
260
|
+
|
|
261
|
+
# Step 1: Resolve library ID
|
|
262
|
+
library_id = await asyncio.wait_for(
|
|
263
|
+
_resolve_library_id(library_name, query),
|
|
264
|
+
timeout=timeout / 2
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
if not library_id:
|
|
268
|
+
return items
|
|
269
|
+
|
|
270
|
+
# Step 2: Query docs with library ID
|
|
271
|
+
docs = await asyncio.wait_for(
|
|
272
|
+
_query_docs(library_id, query),
|
|
273
|
+
timeout=timeout / 2
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
# Step 3: Transform to ContextItems
|
|
277
|
+
for idx, doc in enumerate(docs[:5]): # Limit to 5 results
|
|
278
|
+
items.append(ContextItem(
|
|
279
|
+
id=f"context7:{library_id}:{idx}",
|
|
280
|
+
source="context7",
|
|
281
|
+
title=doc.get('title', f"{library_name} Documentation"),
|
|
282
|
+
summary=doc.get('summary', '')[:200],
|
|
283
|
+
excerpt=doc.get('content', '')[:500],
|
|
284
|
+
relevance=doc.get('score', 0.7),
|
|
285
|
+
age_days=0.0, # External docs are current
|
|
286
|
+
metadata={
|
|
287
|
+
'library_id': library_id,
|
|
288
|
+
'library_name': library_name,
|
|
289
|
+
'url': doc.get('url', ''),
|
|
290
|
+
'source_type': 'external_docs',
|
|
291
|
+
}
|
|
292
|
+
))
|
|
293
|
+
|
|
294
|
+
except asyncio.TimeoutError:
|
|
295
|
+
raise
|
|
296
|
+
except ImportError:
|
|
297
|
+
# MCP tools not available - graceful degradation
|
|
298
|
+
pass # fail open: MCP tools optional
|
|
299
|
+
except Exception as e:
|
|
300
|
+
# Log but don't fail
|
|
301
|
+
print(f"Context7 query error: {e}", file=sys.stderr)
|
|
302
|
+
|
|
303
|
+
return items
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
async def _resolve_library_id(library_name: str, query: str) -> Optional[str]:
|
|
307
|
+
"""
|
|
308
|
+
Resolve library name to Context7 library ID.
|
|
309
|
+
|
|
310
|
+
Uses the Context7 MCP tool: resolve-library-id
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
Library ID (e.g., "/vercel/next.js") or None
|
|
314
|
+
"""
|
|
315
|
+
try:
|
|
316
|
+
# Call Claude Code to invoke MCP tool via subprocess
|
|
317
|
+
# In production, this would use the MCP client directly
|
|
318
|
+
# For now, simulate with a known mapping
|
|
319
|
+
|
|
320
|
+
# Common library mappings (fallback)
|
|
321
|
+
library_map = {
|
|
322
|
+
'react': '/facebook/react',
|
|
323
|
+
'nextjs': '/vercel/next.js',
|
|
324
|
+
'next': '/vercel/next.js',
|
|
325
|
+
'express': '/expressjs/express',
|
|
326
|
+
'fastapi': '/tiangolo/fastapi',
|
|
327
|
+
'django': '/django/django',
|
|
328
|
+
'flask': '/pallets/flask',
|
|
329
|
+
'vue': '/vuejs/core',
|
|
330
|
+
'angular': '/angular/angular',
|
|
331
|
+
'svelte': '/sveltejs/svelte',
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
normalized = library_name.lower().replace('.js', '').replace('-', '')
|
|
335
|
+
return library_map.get(normalized)
|
|
336
|
+
|
|
337
|
+
except Exception as e:
|
|
338
|
+
print(f"Library ID resolution failed for {library_name}: {e}", file=sys.stderr)
|
|
339
|
+
return None
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
async def _query_docs(library_id: str, query: str) -> List[Dict[str, Any]]:
|
|
343
|
+
"""
|
|
344
|
+
Query Context7 documentation for a library ID.
|
|
345
|
+
|
|
346
|
+
Uses the Context7 MCP tool: query-docs
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
List of documentation snippets with metadata
|
|
350
|
+
"""
|
|
351
|
+
try:
|
|
352
|
+
# In production, this would call the actual MCP tool
|
|
353
|
+
# For now, return empty list (graceful degradation)
|
|
354
|
+
# The MCP integration would happen at the hook level
|
|
355
|
+
return []
|
|
356
|
+
|
|
357
|
+
except Exception as e:
|
|
358
|
+
print(f"Doc query failed for {library_id}: {e}", file=sys.stderr)
|
|
359
|
+
return []
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def _extract_library_names(prompt: str) -> List[str]:
|
|
363
|
+
"""
|
|
364
|
+
Extract potential library/framework names from prompt.
|
|
365
|
+
|
|
366
|
+
Uses heuristics to identify references to external libraries:
|
|
367
|
+
- Common library names
|
|
368
|
+
- Package manager patterns (npm install X, pip install X)
|
|
369
|
+
- Import statements
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
prompt: User's query text
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
List of potential library names
|
|
376
|
+
"""
|
|
377
|
+
import re
|
|
378
|
+
|
|
379
|
+
libraries = []
|
|
380
|
+
prompt_lower = prompt.lower()
|
|
381
|
+
|
|
382
|
+
# Pattern 1: Explicit library mentions with common keywords
|
|
383
|
+
library_patterns = [
|
|
384
|
+
r'\b(react|vue|angular|svelte|next(?:js)?|nuxt)\b',
|
|
385
|
+
r'\b(express|fastapi|django|flask|rails|spring)\b',
|
|
386
|
+
r'\b(mongodb|postgres|mysql|redis|elasticsearch)\b',
|
|
387
|
+
r'\b(typescript|python|java|rust|go)\b',
|
|
388
|
+
r'\b(jest|pytest|mocha|cypress|playwright)\b',
|
|
389
|
+
r'\b(webpack|vite|rollup|esbuild|parcel)\b',
|
|
390
|
+
]
|
|
391
|
+
|
|
392
|
+
for pattern in library_patterns:
|
|
393
|
+
matches = re.findall(pattern, prompt_lower)
|
|
394
|
+
libraries.extend(matches)
|
|
395
|
+
|
|
396
|
+
# Pattern 2: Package manager install commands
|
|
397
|
+
install_patterns = [
|
|
398
|
+
r'npm install\s+(@?[\w-]+(?:/[\w-]+)?)',
|
|
399
|
+
r'pip install\s+([\w-]+)',
|
|
400
|
+
r'yarn add\s+(@?[\w-]+(?:/[\w-]+)?)',
|
|
401
|
+
]
|
|
402
|
+
|
|
403
|
+
for pattern in install_patterns:
|
|
404
|
+
matches = re.findall(pattern, prompt_lower)
|
|
405
|
+
libraries.extend(matches)
|
|
406
|
+
|
|
407
|
+
# Pattern 3: Import statements
|
|
408
|
+
import_patterns = [
|
|
409
|
+
r'from\s+([\w-]+)\s+import',
|
|
410
|
+
r'import\s+([\w-]+)',
|
|
411
|
+
r'require\([\'"](@?[\w-]+(?:/[\w-]+)?)[\'"]',
|
|
412
|
+
]
|
|
413
|
+
|
|
414
|
+
for pattern in import_patterns:
|
|
415
|
+
matches = re.findall(pattern, prompt)
|
|
416
|
+
libraries.extend(matches)
|
|
417
|
+
|
|
418
|
+
# Deduplicate and clean
|
|
419
|
+
unique_libs = []
|
|
420
|
+
seen = set()
|
|
421
|
+
for lib in libraries:
|
|
422
|
+
# Clean up library name
|
|
423
|
+
lib = lib.strip().lower()
|
|
424
|
+
|
|
425
|
+
# Skip built-ins and common false positives
|
|
426
|
+
skip_list = {'os', 'sys', 'json', 'time', 're', 'math', 'from', 'import'}
|
|
427
|
+
if lib in skip_list or len(lib) < 2:
|
|
428
|
+
continue
|
|
429
|
+
|
|
430
|
+
if lib not in seen:
|
|
431
|
+
seen.add(lib)
|
|
432
|
+
unique_libs.append(lib)
|
|
433
|
+
|
|
434
|
+
return unique_libs[:5] # Limit to 5 libraries
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
# Public API
|
|
438
|
+
__all__ = ['query', 'Context7Cache']
|