specsmith 0.12.0.dev494__tar.gz → 0.12.0.dev497__tar.gz
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.
- {specsmith-0.12.0.dev494/src/specsmith.egg-info → specsmith-0.12.0.dev497}/PKG-INFO +1 -1
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/pyproject.toml +1 -1
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/auditor.py +65 -4
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/cli.py +186 -56
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/config.py +66 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/importer.py +66 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/mcp_server.py +113 -15
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/scaffolder.py +169 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/__init__.py +17 -0
- specsmith-0.12.0.dev497/src/specsmith/skills/ai_agents.py +1439 -0
- specsmith-0.12.0.dev497/src/specsmith/skills/data_engineering.py +960 -0
- specsmith-0.12.0.dev497/src/specsmith/skills/platform_engineering.py +1391 -0
- specsmith-0.12.0.dev497/src/specsmith/skills/software_engineering.py +1291 -0
- specsmith-0.12.0.dev497/src/specsmith/skills/web_backend.py +1427 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/tools.py +123 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497/src/specsmith.egg-info}/PKG-INFO +1 -1
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith.egg-info/SOURCES.txt +5 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_auditor.py +89 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_mcp_server.py +99 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/LICENSE +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/README.md +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/setup.cfg +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/belief.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/certainty.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/failure_graph.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/py.typed +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/recovery.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/session.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/stress_tester.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/epistemic/trace.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/__main__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/broker.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/chat_runner.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/cleanup.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/context_seed.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/core.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/dispatch/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/dispatch/_status.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/dispatch/dag.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/dispatch/events.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/dispatch/result.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/endpoints.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/events.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/execution_profiles.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/fallback.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/hf_leaderboard.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/hf_sync.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/indexer.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/llm_client.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/mcp.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/memory.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/model_intelligence.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/model_profiles.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/orchestrator.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/permissions.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/profiles.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/provider_registry.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/repl.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/router.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/rules.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/runner.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/safety.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/spawner.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/suggester.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/teams.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/tools.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/verifier.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/agent/voice.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/architect.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/auth.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/block_export.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/channel.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/ci_manager.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/commands/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/commands/intelligence.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/compliance/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/compliance/_compat.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/compliance/checker.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/compliance/evidence.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/compliance/regulations.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/compliance/reporter.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/compressor.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/console_utils.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/context_orchestrator.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/context_window.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/credit_analyzer.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/credits.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/base.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/citations.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/fpd.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/odp.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/patentsview.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/pfw.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/ppubs.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/datasources/ptab.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/differ.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/doctor.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/drive.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/editor.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/epistemic/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/epistemic/belief.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/epistemic/certainty.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/epistemic/failure_graph.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/epistemic/recovery.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/epistemic/stress_tester.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/esdb/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/esdb/bridge.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/eval/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/eval/builtins.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/eval/runner.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/executor.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/exporter.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/governance_logic.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/governance_store.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/governance_yaml.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/app.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/main_window.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/session_tab.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/theme.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/widgets/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/widgets/chat_view.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/widgets/input_bar.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/widgets/provider_bar.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/widgets/token_meter.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/widgets/tool_panel.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/widgets/update_checker.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/gui/worker.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/history_search.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/instinct.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/agent_skill.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/aider.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/base.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/claude_code.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/codity.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/copilot.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/cursor.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/gemini.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/integrations/windsurf.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/issue_reporter.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/languages.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/ledger.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/mcp_generator.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/m002_agents_slim.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/m003_compliance_init.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/m006_session_governance.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/migrations/runner.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/ollama_cmds.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/patent.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/paths.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/phase.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/plugins.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/profiles.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/rate_limits.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/releaser.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/requirements.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/requirements_parser.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/retrieval.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/safe_write.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/serve.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/session.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/session_init.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/session_store.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/cloud.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/corporate.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/cross_platform.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/devops.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/docs.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/embedded.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/governance.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/hardware.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/mobile.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/productivity.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/specsmith_skills.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills/ssh.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/skills_builder.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/sync.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/agents.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/contributing.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/license-MIT.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/community/security.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/editorconfig.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/gitattributes.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/gitignore.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/go/go.mod.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/go/main.go.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/roles.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/rules.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/governance/verification.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/js/package.json.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/ledger.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/python/cli.py.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/python/init.py.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/readme.md.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/rust/main.rs.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/tool_installer.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/toolrules.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/trace.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/updater.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/upgrader.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/validator.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/vcs/__init__.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/vcs/base.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/vcs/bitbucket.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/vcs/github.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/vcs/gitlab.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/vcs_commands.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/wireframes.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith/workspace.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith.egg-info/dependency_links.txt +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith.egg-info/entry_points.txt +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith.egg-info/requires.txt +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/src/specsmith.egg-info/top_level.txt +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_CMD_001.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_agent_profiles.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_agent_run_feedback.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_agent_runner_ready.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_ai_client.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_ai_intelligence.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_channel.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_chat_diff_decision.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_chat_runner_openai_compat.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_chat_stdin_protocol.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_cli.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_cli_workflows_history_drive.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_compliance.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_compressor.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_dispatch.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_e2e_nexus.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_endpoints_cli.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_endpoints_store.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_epistemic.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_fallback_chain.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_importer.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_integrations.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_integrations_codity.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_intelligence.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_issue_reporter.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_mcp_client.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_new_modules.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_nexus.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_permissions.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_phase1_4_new.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_phase34_completion.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_rate_limits.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_req_248_262.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_req_358_359.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_scaffolder.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_skill_marketplace.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_skills_mcp.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_smoke.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_suggester.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_tools.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_validator.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_vcs.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_warp_parity.py +0 -0
- {specsmith-0.12.0.dev494 → specsmith-0.12.0.dev497}/tests/test_warp_parity_followup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specsmith
|
|
3
|
-
Version: 0.12.0.
|
|
3
|
+
Version: 0.12.0.dev497
|
|
4
4
|
Summary: Applied Epistemic Engineering toolkit — AEE agent sessions, execution profiles, FPGA/HDL governance, tool installer, 50+ CLI commands.
|
|
5
5
|
Author: BitConcepts
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specsmith"
|
|
7
|
-
version = "0.12.0.
|
|
7
|
+
version = "0.12.0.dev497"
|
|
8
8
|
description = "Applied Epistemic Engineering toolkit — AEE agent sessions, execution profiles, FPGA/HDL governance, tool installer, 50+ CLI commands."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -441,9 +441,11 @@ def check_ledger_health(root: Path) -> list[AuditResult]:
|
|
|
441
441
|
)
|
|
442
442
|
)
|
|
443
443
|
|
|
444
|
-
# Open TODOs
|
|
445
|
-
|
|
446
|
-
|
|
444
|
+
# Open TODOs — only count lines where the checklist marker is at the
|
|
445
|
+
# start of the trimmed line, not prose references such as:
|
|
446
|
+
# "- TODO closure: all 109 - [ ] items changed to - [x]"
|
|
447
|
+
open_todos = sum(1 for line in lines if line.lstrip().startswith("- [ ]"))
|
|
448
|
+
closed_todos = sum(1 for line in lines if line.lstrip().startswith("- [x]"))
|
|
447
449
|
if open_todos > 20:
|
|
448
450
|
results.append(
|
|
449
451
|
AuditResult(
|
|
@@ -715,8 +717,53 @@ def check_tool_configuration(root: Path) -> list[AuditResult]:
|
|
|
715
717
|
return results
|
|
716
718
|
|
|
717
719
|
|
|
720
|
+
# Types that require explicit configuration and cannot be reliably inferred
|
|
721
|
+
# from file-extension counts alone. When a project declares one of these,
|
|
722
|
+
# auto-detection is skipped so that auxiliary tooling languages (e.g. Python
|
|
723
|
+
# verification scripts in an FPGA project) do not produce a false-positive
|
|
724
|
+
# mismatch. See GitHub issue #194.
|
|
725
|
+
_EXPLICIT_ONLY_TYPES: frozenset[str] = frozenset(
|
|
726
|
+
[
|
|
727
|
+
# Hardware / vendor-specific types that cannot be auto-detected from
|
|
728
|
+
# file extensions (Python/C tooling dominates file counts).
|
|
729
|
+
"fpga-rtl",
|
|
730
|
+
"fpga-rtl-amd",
|
|
731
|
+
"fpga-rtl-intel",
|
|
732
|
+
"fpga-rtl-lattice",
|
|
733
|
+
"mixed-fpga-embedded",
|
|
734
|
+
"mixed-fpga-firmware",
|
|
735
|
+
"embedded-hardware",
|
|
736
|
+
"pcb-hardware",
|
|
737
|
+
"yocto-bsp",
|
|
738
|
+
# Infrastructure types where auxiliary Python/JS glue code dominates
|
|
739
|
+
# and a generic detection pass would misclassify the primary type.
|
|
740
|
+
"kubernetes-operator",
|
|
741
|
+
"streaming-pipeline",
|
|
742
|
+
"serverless",
|
|
743
|
+
# AI / agent types: an LLM app is indistinguishable from a regular
|
|
744
|
+
# Python library unless dependency signals are present. Suppress
|
|
745
|
+
# false-positive mismatches when the type is set explicitly.
|
|
746
|
+
"agent-orchestration",
|
|
747
|
+
"mcp-server",
|
|
748
|
+
"rag-pipeline",
|
|
749
|
+
"mlops-platform",
|
|
750
|
+
# Game engines: Unity / Godot projects often have Python tooling alongside.
|
|
751
|
+
"game-unity",
|
|
752
|
+
"game-godot",
|
|
753
|
+
# Data warehouse: dbt + SQL projects have no primary-language file bias.
|
|
754
|
+
"data-warehouse",
|
|
755
|
+
]
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
|
|
718
759
|
def check_type_mismatch(root: Path) -> list[AuditResult]:
|
|
719
|
-
"""Check if scaffold.yml type matches actual detected project type.
|
|
760
|
+
"""Check if scaffold.yml type matches actual detected project type.
|
|
761
|
+
|
|
762
|
+
For hardware / vendor-specific types that cannot be auto-detected from
|
|
763
|
+
file-extension counts (see ``_EXPLICIT_ONLY_TYPES``), the detection step
|
|
764
|
+
is skipped entirely so that auxiliary languages (e.g. Python scripts in an
|
|
765
|
+
FPGA project) never produce a false-positive mismatch.
|
|
766
|
+
"""
|
|
720
767
|
results: list[AuditResult] = []
|
|
721
768
|
scaffold_path = root / "scaffold.yml"
|
|
722
769
|
if not scaffold_path.exists():
|
|
@@ -731,6 +778,20 @@ def check_type_mismatch(root: Path) -> list[AuditResult]:
|
|
|
731
778
|
with open(scaffold_path) as f:
|
|
732
779
|
raw = yaml.safe_load(f)
|
|
733
780
|
config = ProjectConfig(**raw)
|
|
781
|
+
|
|
782
|
+
# Skip auto-detection for types that must be specified explicitly.
|
|
783
|
+
if config.type in _EXPLICIT_ONLY_TYPES:
|
|
784
|
+
results.append(
|
|
785
|
+
AuditResult(
|
|
786
|
+
name="type-mismatch",
|
|
787
|
+
passed=True,
|
|
788
|
+
message=(
|
|
789
|
+
f"Project type {config.type} is explicitly set; auto-detection skipped"
|
|
790
|
+
),
|
|
791
|
+
)
|
|
792
|
+
)
|
|
793
|
+
return results
|
|
794
|
+
|
|
734
795
|
detected = detect_project(root)
|
|
735
796
|
if detected.inferred_type and detected.inferred_type != config.type:
|
|
736
797
|
results.append(
|
|
@@ -350,6 +350,16 @@ def init(config_path: str | None, output_dir: str, no_git: bool, guided: bool) -
|
|
|
350
350
|
|
|
351
351
|
write_phase(target, "inception")
|
|
352
352
|
|
|
353
|
+
# Auto-register with the MCP governance server (best-effort, never blocks)
|
|
354
|
+
with contextlib.suppress(Exception):
|
|
355
|
+
from specsmith.mcp_server import register_project
|
|
356
|
+
|
|
357
|
+
if register_project(str(target)):
|
|
358
|
+
console.print(
|
|
359
|
+
" [dim]\u2713 Registered with MCP server "
|
|
360
|
+
"([bold]specsmith mcp projects[/bold] to view)[/dim]"
|
|
361
|
+
)
|
|
362
|
+
|
|
353
363
|
|
|
354
364
|
def _load_config_with_inheritance(config_path: str) -> dict[str, object]:
|
|
355
365
|
"""Load scaffold.yml, merging parent config if `extends` is set."""
|
|
@@ -1746,6 +1756,16 @@ def import_project(
|
|
|
1746
1756
|
console.print(f"\n[bold green]Done.[/bold green] {len(created)} governance files generated.")
|
|
1747
1757
|
console.print("Governance files generated. Review project configuration.")
|
|
1748
1758
|
|
|
1759
|
+
# Auto-register with the MCP governance server (best-effort, never blocks)
|
|
1760
|
+
with contextlib.suppress(Exception):
|
|
1761
|
+
from specsmith.mcp_server import register_project
|
|
1762
|
+
|
|
1763
|
+
if register_project(str(root)):
|
|
1764
|
+
console.print(
|
|
1765
|
+
" [dim]\u2713 Registered with MCP server "
|
|
1766
|
+
"([bold]specsmith mcp projects[/bold] to view)[/dim]"
|
|
1767
|
+
)
|
|
1768
|
+
|
|
1749
1769
|
|
|
1750
1770
|
def _run_guided_architecture(cfg: ProjectConfig, target: Path) -> list[Path]:
|
|
1751
1771
|
"""Run interactive architecture definition and generate REQ/TEST stubs."""
|
|
@@ -9049,46 +9069,44 @@ def mcp_list_cmd(project_dir: str, as_json: bool) -> None:
|
|
|
9049
9069
|
|
|
9050
9070
|
|
|
9051
9071
|
@mcp_group.command(name="serve")
|
|
9052
|
-
@click.option(
|
|
9072
|
+
@click.option(
|
|
9073
|
+
"--project-dir",
|
|
9074
|
+
type=click.Path(),
|
|
9075
|
+
default=None,
|
|
9076
|
+
help=(
|
|
9077
|
+
"Set this path as the *primary* project (first slot / default for tool calls "
|
|
9078
|
+
"that omit project_dir). Omit to use the registry automatically."
|
|
9079
|
+
),
|
|
9080
|
+
)
|
|
9053
9081
|
@click.option(
|
|
9054
9082
|
"--project-dirs",
|
|
9055
9083
|
default="",
|
|
9056
9084
|
help=(
|
|
9057
|
-
"
|
|
9058
|
-
"All registered projects are accessible to any tool call via their "
|
|
9059
|
-
"absolute path as the project_dir argument."
|
|
9085
|
+
"Extra project directories to add on top of the registry (comma-separated absolute paths)."
|
|
9060
9086
|
),
|
|
9061
9087
|
)
|
|
9062
|
-
def mcp_serve_cmd(project_dir: str, project_dirs: str) -> None:
|
|
9088
|
+
def mcp_serve_cmd(project_dir: str | None, project_dirs: str) -> None:
|
|
9063
9089
|
"""Start the native governance MCP stdio server (REQ-363).
|
|
9064
9090
|
|
|
9065
9091
|
Implements MCP 2024-11-05 over stdin/stdout (JSON-RPC 2.0).
|
|
9066
|
-
Exposes seven governance tools to any MCP client
|
|
9092
|
+
Exposes seven governance tools to any MCP client.
|
|
9067
9093
|
|
|
9068
9094
|
\b
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
governance_preflight Preflight a change intent
|
|
9073
|
-
governance_phase Current AEE phase + readiness %
|
|
9074
|
-
governance_req_list List all requirements
|
|
9075
|
-
governance_trace_seal Seal a milestone/decision
|
|
9095
|
+
Recommended Warp config (set once, never touch again)::
|
|
9096
|
+
|
|
9097
|
+
{"specsmith-governance": {"command": "specsmith", "args": ["mcp", "serve"]}}
|
|
9076
9098
|
|
|
9077
9099
|
\b
|
|
9078
|
-
|
|
9100
|
+
Then register each project once from inside that project::
|
|
9079
9101
|
|
|
9080
|
-
|
|
9081
|
-
"args": ["mcp", "serve", "--project-dir", "/path/to/project"]}}
|
|
9102
|
+
specsmith mcp register
|
|
9082
9103
|
|
|
9083
9104
|
\b
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
{"specsmith-governance": {"command": "specsmith",
|
|
9087
|
-
"args": ["mcp", "serve", "--project-dir", "/path/to/proj1",
|
|
9088
|
-
"--project-dirs", "/path/to/proj2,/path/to/proj3"]}}
|
|
9105
|
+
The server reads the registry at startup and serves all registered
|
|
9106
|
+
projects automatically — no config changes needed for new projects.
|
|
9089
9107
|
|
|
9090
9108
|
\b
|
|
9091
|
-
Or pass inline to oz (use ``specsmith mcp install-warp`` for the
|
|
9109
|
+
Or pass inline to oz (use ``specsmith mcp install-warp`` for the snippet)::
|
|
9092
9110
|
|
|
9093
9111
|
oz agent run --mcp "$(specsmith mcp install-warp --json)" --prompt "..."
|
|
9094
9112
|
"""
|
|
@@ -9099,42 +9117,52 @@ def mcp_serve_cmd(project_dir: str, project_dirs: str) -> None:
|
|
|
9099
9117
|
|
|
9100
9118
|
|
|
9101
9119
|
@mcp_group.command(name="install-warp")
|
|
9102
|
-
@click.option("--project-dir", type=click.Path(), default=".", show_default=True)
|
|
9103
|
-
@click.option(
|
|
9104
|
-
"--project-dirs",
|
|
9105
|
-
default="",
|
|
9106
|
-
help="Additional project dirs (comma-separated) to include in the multi-project config.",
|
|
9107
|
-
)
|
|
9108
9120
|
@click.option("--json", "as_json", is_flag=True, default=False, help="Emit JSON config only.")
|
|
9109
|
-
def mcp_install_warp_cmd(
|
|
9121
|
+
def mcp_install_warp_cmd(as_json: bool) -> None:
|
|
9110
9122
|
"""Print the Warp MCP config snippet for the governance server (REQ-363).
|
|
9111
9123
|
|
|
9124
|
+
Generates a minimal, registry-aware config — paste it into Warp once
|
|
9125
|
+
and never change it again. Register new projects with::
|
|
9126
|
+
|
|
9127
|
+
specsmith mcp register # in the project directory
|
|
9128
|
+
|
|
9112
9129
|
Copy the output into Warp Settings → Agents → MCP servers, or pass it
|
|
9113
9130
|
to ``oz agent run --mcp '<json>'`` for a one-off cloud agent run.
|
|
9114
|
-
|
|
9115
|
-
For multi-project setups pass ``--project-dirs`` with comma-separated
|
|
9116
|
-
absolute paths; one server instance will serve all projects.
|
|
9117
9131
|
"""
|
|
9118
9132
|
import json as _json
|
|
9119
9133
|
import shutil
|
|
9120
9134
|
import sys
|
|
9121
9135
|
|
|
9122
|
-
#
|
|
9123
|
-
#
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9136
|
+
# Env vars the server needs regardless of how it is invoked.
|
|
9137
|
+
# SPECSMITH_ALLOW_NON_PIPX=1 — prevents the pipx-enforcement gate from
|
|
9138
|
+
# exiting before the MCP handshake when Warp starts the server directly.
|
|
9139
|
+
# SPECSMITH_NO_AUTO_UPDATE / SPECSMITH_PYPI_CHECKED — suppress network
|
|
9140
|
+
# calls on startup so the server responds immediately.
|
|
9141
|
+
server_env = {
|
|
9142
|
+
"SPECSMITH_ALLOW_NON_PIPX": "1",
|
|
9143
|
+
"SPECSMITH_NO_AUTO_UPDATE": "1",
|
|
9144
|
+
"SPECSMITH_PYPI_CHECKED": "1",
|
|
9145
|
+
}
|
|
9129
9146
|
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9147
|
+
# Executable detection strategy (in priority order):
|
|
9148
|
+
# 1. specsmith (or specsmith.exe) on PATH — covers pipx shims and system installs.
|
|
9149
|
+
# 2. python -m specsmith via the current interpreter — reliable fallback
|
|
9150
|
+
# for editable dev installs and venvs where the console script wrapper
|
|
9151
|
+
# is absent or resolves incorrectly (e.g. some Windows pipx setups).
|
|
9152
|
+
specsmith_exe = shutil.which("specsmith") or shutil.which("specsmith.exe")
|
|
9153
|
+
if specsmith_exe:
|
|
9154
|
+
cmd = specsmith_exe
|
|
9155
|
+
args: list[str] = ["mcp", "serve"]
|
|
9156
|
+
else:
|
|
9157
|
+
# Fall back to `python -m specsmith` using the current interpreter.
|
|
9158
|
+
cmd = sys.executable
|
|
9159
|
+
args = ["-m", "specsmith", "mcp", "serve"]
|
|
9133
9160
|
|
|
9134
9161
|
config = {
|
|
9135
9162
|
"specsmith-governance": {
|
|
9136
|
-
"command":
|
|
9163
|
+
"command": cmd,
|
|
9137
9164
|
"args": args,
|
|
9165
|
+
"env": server_env,
|
|
9138
9166
|
}
|
|
9139
9167
|
}
|
|
9140
9168
|
|
|
@@ -9148,22 +9176,124 @@ def mcp_install_warp_cmd(project_dir: str, project_dirs: str, as_json: bool) ->
|
|
|
9148
9176
|
"or pass inline to [bold]oz agent run --mcp '<json>'[/bold]:\n"
|
|
9149
9177
|
)
|
|
9150
9178
|
console.print(_json.dumps(config, indent=2))
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9179
|
+
console.print(
|
|
9180
|
+
"\n[dim][bold]One-time setup[/bold] — paste this config into Warp once," # noqa: E501
|
|
9181
|
+
" then never touch it again.\n"
|
|
9182
|
+
"\nTo add each project, run this inside the project directory:\n"
|
|
9183
|
+
" [bold]specsmith mcp register[/bold]\n"
|
|
9184
|
+
"\nThe server reads [bold]~/.specsmith/mcp-projects.json[/bold] at startup\n"
|
|
9185
|
+
"and serves all registered projects automatically.\n"
|
|
9186
|
+
"\nView registered projects: [bold]specsmith mcp projects[/bold]\n"
|
|
9187
|
+
"\nVerify server: specsmith mcp serve (then send an initialize message).[/dim]"
|
|
9188
|
+
)
|
|
9189
|
+
|
|
9190
|
+
|
|
9191
|
+
@mcp_group.command(name="register")
|
|
9192
|
+
@click.argument("path", default=".", required=False)
|
|
9193
|
+
def mcp_register_cmd(path: str) -> None:
|
|
9194
|
+
"""Register a project directory with the MCP server registry.
|
|
9195
|
+
|
|
9196
|
+
Run once inside a project directory to add it to
|
|
9197
|
+
``~/.specsmith/mcp-projects.json``. The next ``specsmith mcp serve``
|
|
9198
|
+
invocation will automatically include it — no Warp config changes needed.
|
|
9199
|
+
|
|
9200
|
+
\b
|
|
9201
|
+
Examples::
|
|
9202
|
+
|
|
9203
|
+
specsmith mcp register # register current directory
|
|
9204
|
+
specsmith mcp register /path/to/myproject
|
|
9205
|
+
"""
|
|
9206
|
+
from specsmith.mcp_server import register_project
|
|
9207
|
+
|
|
9208
|
+
root = Path(path).resolve()
|
|
9209
|
+
if not root.exists():
|
|
9210
|
+
console.print(f"[red]\u2717[/red] Path does not exist: {root}")
|
|
9211
|
+
raise SystemExit(1)
|
|
9212
|
+
|
|
9213
|
+
added = register_project(str(root))
|
|
9214
|
+
if added:
|
|
9215
|
+
console.print(f"[green]\u2713[/green] Registered: [bold]{root}[/bold]")
|
|
9216
|
+
if not (root / ".specsmith").exists():
|
|
9217
|
+
console.print(
|
|
9218
|
+
" [yellow]\u26a0[/yellow] No .specsmith/ found. "
|
|
9219
|
+
"Run [bold]specsmith init[/bold] or [bold]specsmith import[/bold] first."
|
|
9220
|
+
)
|
|
9157
9221
|
else:
|
|
9222
|
+
console.print(f"[dim]Already registered: {root}[/dim]")
|
|
9223
|
+
console.print(
|
|
9224
|
+
" [dim]specsmith mcp projects ← view all registered[/dim]\n"
|
|
9225
|
+
" [dim]specsmith mcp serve ← start the server[/dim]"
|
|
9226
|
+
)
|
|
9227
|
+
|
|
9228
|
+
|
|
9229
|
+
@mcp_group.command(name="unregister")
|
|
9230
|
+
@click.argument("path", default=".", required=False)
|
|
9231
|
+
def mcp_unregister_cmd(path: str) -> None:
|
|
9232
|
+
"""Remove a project directory from the MCP server registry.
|
|
9233
|
+
|
|
9234
|
+
\b
|
|
9235
|
+
Examples::
|
|
9236
|
+
|
|
9237
|
+
specsmith mcp unregister # unregister current directory
|
|
9238
|
+
specsmith mcp unregister /path/to/myproject
|
|
9239
|
+
"""
|
|
9240
|
+
from specsmith.mcp_server import unregister_project
|
|
9241
|
+
|
|
9242
|
+
root = Path(path).resolve()
|
|
9243
|
+
removed = unregister_project(str(root))
|
|
9244
|
+
if removed:
|
|
9245
|
+
console.print(f"[green]\u2713[/green] Unregistered: [bold]{root}[/bold]")
|
|
9246
|
+
else:
|
|
9247
|
+
console.print(f"[yellow]Not registered: {root}[/yellow]")
|
|
9248
|
+
|
|
9249
|
+
|
|
9250
|
+
@mcp_group.command(name="projects")
|
|
9251
|
+
@click.option("--json", "as_json", is_flag=True, default=False, help="Emit as JSON.")
|
|
9252
|
+
def mcp_projects_cmd(as_json: bool) -> None:
|
|
9253
|
+
"""List all projects registered with the MCP server.
|
|
9254
|
+
|
|
9255
|
+
Shows each registered project path and whether it still exists on disk.
|
|
9256
|
+
The first entry is the default (used when a tool call omits project_dir).
|
|
9257
|
+
"""
|
|
9258
|
+
import json as _json
|
|
9259
|
+
import os
|
|
9260
|
+
|
|
9261
|
+
from specsmith.mcp_server import _registry_file, read_registry
|
|
9262
|
+
|
|
9263
|
+
projects = read_registry()
|
|
9264
|
+
reg_path = _registry_file()
|
|
9265
|
+
|
|
9266
|
+
if as_json:
|
|
9267
|
+
entries = [
|
|
9268
|
+
{"path": p, "exists": Path(p).exists(), "is_default": i == 0}
|
|
9269
|
+
for i, p in enumerate(projects)
|
|
9270
|
+
]
|
|
9271
|
+
click.echo(_json.dumps({"registry": str(reg_path), "projects": entries}, indent=2))
|
|
9272
|
+
return
|
|
9273
|
+
|
|
9274
|
+
if not projects:
|
|
9275
|
+
console.print("[yellow]No projects registered.[/yellow]")
|
|
9158
9276
|
console.print(
|
|
9159
|
-
"
|
|
9160
|
-
"governance_audit, governance_preflight,\n"
|
|
9161
|
-
"governance_checkpoint, governance_phase, governance_req_list, and\n"
|
|
9162
|
-
"governance_trace_seal as structured MCP tool calls.\n"
|
|
9163
|
-
"\nFor multiple projects add --project-dirs /path/a,/path/b to serve them "
|
|
9164
|
-
"all from one server instance.\n"
|
|
9165
|
-
"\nVerify with: specsmith mcp serve (then send an initialize message).[/dim]"
|
|
9277
|
+
"[dim]Run [bold]specsmith mcp register[/bold] inside a project to add it.[/dim]"
|
|
9166
9278
|
)
|
|
9279
|
+
return
|
|
9280
|
+
|
|
9281
|
+
console.print(
|
|
9282
|
+
f"[bold]Registered MCP projects[/bold] ({len(projects)}) [dim]{reg_path}[/dim]\n"
|
|
9283
|
+
)
|
|
9284
|
+
for i, p in enumerate(projects):
|
|
9285
|
+
exists = Path(p).exists()
|
|
9286
|
+
default_tag = " [bold cyan][default][/bold cyan]" if i == 0 else ""
|
|
9287
|
+
health = "[green]\u2713 exists[/green]" if exists else "[red]\u2717 not found[/red]"
|
|
9288
|
+
# Abbreviate long paths using ~ for home
|
|
9289
|
+
display = p.replace(os.path.expanduser("~"), "~")
|
|
9290
|
+
console.print(f" {health} {display}{default_tag}")
|
|
9291
|
+
|
|
9292
|
+
console.print(
|
|
9293
|
+
"\n[dim] specsmith mcp register [path] ← add a project"
|
|
9294
|
+
"\n specsmith mcp unregister [path] ← remove a project"
|
|
9295
|
+
"\n specsmith mcp serve ← start the server[/dim]"
|
|
9296
|
+
)
|
|
9167
9297
|
|
|
9168
9298
|
|
|
9169
9299
|
main.add_command(mcp_group)
|
|
@@ -74,6 +74,28 @@ class ProjectType(str, Enum):
|
|
|
74
74
|
SVELTEKIT_APP = "sveltekit-app" # SvelteKit app
|
|
75
75
|
REMIX_APP = "remix-app" # Remix full-stack React app
|
|
76
76
|
ASTRO_SITE = "astro-site" # Astro static/SSR site
|
|
77
|
+
# AI / LLM / Agents
|
|
78
|
+
LLM_APP = "llm-app" # LLM-powered app (LangChain / LlamaIndex / custom SDK)
|
|
79
|
+
AGENT_ORCHESTRATION = "agent-orchestration" # Multi-agent system (AutoGen/CrewAI/LangGraph)
|
|
80
|
+
MCP_SERVER = "mcp-server" # Model Context Protocol server
|
|
81
|
+
RAG_PIPELINE = "rag-pipeline" # RAG + embedding pipeline
|
|
82
|
+
MLOPS_PLATFORM = "mlops-platform" # MLOps platform (MLflow / BentoML / Ray Serve)
|
|
83
|
+
# JVM
|
|
84
|
+
JAVA_SPRING = "java-spring" # Spring Boot application
|
|
85
|
+
JAVA_LIBRARY = "java-library" # Java library / SDK
|
|
86
|
+
# Cloud / Infrastructure
|
|
87
|
+
SERVERLESS = "serverless" # FaaS (Lambda / GCP Functions / Cloudflare Workers)
|
|
88
|
+
KUBERNETES_OPERATOR = "kubernetes-operator" # K8s controller / operator
|
|
89
|
+
STREAMING_PIPELINE = "streaming-pipeline" # Kafka / Flink / Beam / Spark Streaming
|
|
90
|
+
DATA_WAREHOUSE = "data-warehouse" # dbt / Snowflake / BigQuery / Redshift
|
|
91
|
+
# Game development
|
|
92
|
+
GAME_UNITY = "game-unity" # Unity game project
|
|
93
|
+
GAME_GODOT = "game-godot" # Godot game project
|
|
94
|
+
# Web3 / blockchain
|
|
95
|
+
SMART_CONTRACT = "smart-contract" # Solidity / EVM smart contracts
|
|
96
|
+
# Desktop
|
|
97
|
+
DESKTOP_ELECTRON = "desktop-electron" # Electron desktop app
|
|
98
|
+
DESKTOP_TAURI = "desktop-tauri" # Tauri desktop app (Rust + WebView)
|
|
77
99
|
|
|
78
100
|
|
|
79
101
|
class Platform(str, Enum):
|
|
@@ -548,6 +570,28 @@ _TYPE_LABELS: dict[str, str] = {
|
|
|
548
570
|
ProjectType.SVELTEKIT_APP: "SvelteKit application",
|
|
549
571
|
ProjectType.REMIX_APP: "Remix application (React + full-stack)",
|
|
550
572
|
ProjectType.ASTRO_SITE: "Astro site (static / SSR)",
|
|
573
|
+
# AI / LLM / Agents
|
|
574
|
+
ProjectType.LLM_APP: "LLM-powered application (LangChain / LlamaIndex / custom)",
|
|
575
|
+
ProjectType.AGENT_ORCHESTRATION: "Multi-agent orchestration (AutoGen / CrewAI / LangGraph)",
|
|
576
|
+
ProjectType.MCP_SERVER: "MCP server (Model Context Protocol)",
|
|
577
|
+
ProjectType.RAG_PIPELINE: "RAG / embedding pipeline",
|
|
578
|
+
ProjectType.MLOPS_PLATFORM: "MLOps platform (MLflow / BentoML / Ray Serve)",
|
|
579
|
+
# JVM
|
|
580
|
+
ProjectType.JAVA_SPRING: "Java Spring Boot application",
|
|
581
|
+
ProjectType.JAVA_LIBRARY: "Java library / SDK",
|
|
582
|
+
# Cloud / Infrastructure
|
|
583
|
+
ProjectType.SERVERLESS: "Serverless / FaaS (Lambda / GCP Functions / Cloudflare Workers)",
|
|
584
|
+
ProjectType.KUBERNETES_OPERATOR: "Kubernetes operator / controller",
|
|
585
|
+
ProjectType.STREAMING_PIPELINE: "Streaming data pipeline (Kafka / Flink / Beam)",
|
|
586
|
+
ProjectType.DATA_WAREHOUSE: "Data warehouse (dbt / Snowflake / BigQuery)",
|
|
587
|
+
# Game development
|
|
588
|
+
ProjectType.GAME_UNITY: "Game (Unity)",
|
|
589
|
+
ProjectType.GAME_GODOT: "Game (Godot)",
|
|
590
|
+
# Web3
|
|
591
|
+
ProjectType.SMART_CONTRACT: "Smart contract (Solidity / EVM)",
|
|
592
|
+
# Desktop
|
|
593
|
+
ProjectType.DESKTOP_ELECTRON: "Desktop application (Electron)",
|
|
594
|
+
ProjectType.DESKTOP_TAURI: "Desktop application (Tauri — Rust + WebView)",
|
|
551
595
|
}
|
|
552
596
|
|
|
553
597
|
_SECTION_REFS: dict[str, str] = {
|
|
@@ -584,4 +628,26 @@ _SECTION_REFS: dict[str, str] = {
|
|
|
584
628
|
ProjectType.EPISTEMIC_PIPELINE: "17.31",
|
|
585
629
|
ProjectType.KNOWLEDGE_ENGINEERING: "17.32",
|
|
586
630
|
ProjectType.AEE_RESEARCH: "17.33",
|
|
631
|
+
# AI / LLM / Agents
|
|
632
|
+
ProjectType.LLM_APP: "17.34",
|
|
633
|
+
ProjectType.AGENT_ORCHESTRATION: "17.35",
|
|
634
|
+
ProjectType.MCP_SERVER: "17.36",
|
|
635
|
+
ProjectType.RAG_PIPELINE: "17.37",
|
|
636
|
+
ProjectType.MLOPS_PLATFORM: "17.38",
|
|
637
|
+
# JVM
|
|
638
|
+
ProjectType.JAVA_SPRING: "17.39",
|
|
639
|
+
ProjectType.JAVA_LIBRARY: "17.40",
|
|
640
|
+
# Cloud / Infrastructure
|
|
641
|
+
ProjectType.SERVERLESS: "17.41",
|
|
642
|
+
ProjectType.KUBERNETES_OPERATOR: "17.42",
|
|
643
|
+
ProjectType.STREAMING_PIPELINE: "17.43",
|
|
644
|
+
ProjectType.DATA_WAREHOUSE: "17.44",
|
|
645
|
+
# Game development
|
|
646
|
+
ProjectType.GAME_UNITY: "17.45",
|
|
647
|
+
ProjectType.GAME_GODOT: "17.46",
|
|
648
|
+
# Web3
|
|
649
|
+
ProjectType.SMART_CONTRACT: "17.47",
|
|
650
|
+
# Desktop
|
|
651
|
+
ProjectType.DESKTOP_ELECTRON: "17.48",
|
|
652
|
+
ProjectType.DESKTOP_TAURI: "17.49",
|
|
587
653
|
}
|
|
@@ -1142,15 +1142,81 @@ def _infer_type(result: DetectionResult) -> ProjectType:
|
|
|
1142
1142
|
pkg = result.root / "package.json"
|
|
1143
1143
|
if pkg.exists():
|
|
1144
1144
|
content = pkg.read_text(encoding="utf-8")
|
|
1145
|
+
if "electron" in content:
|
|
1146
|
+
return ProjectType.DESKTOP_ELECTRON
|
|
1147
|
+
if "solidity" in content or "hardhat" in content or "ethers" in content:
|
|
1148
|
+
return ProjectType.SMART_CONTRACT
|
|
1149
|
+
if (result.root / "serverless.yml").exists() or (
|
|
1150
|
+
result.root / "wrangler.toml"
|
|
1151
|
+
).exists():
|
|
1152
|
+
return ProjectType.SERVERLESS
|
|
1145
1153
|
if "react" in content or "vue" in content or "angular" in content:
|
|
1146
1154
|
# Check if there's also a server
|
|
1147
1155
|
if (result.root / "server").exists() or "express" in content:
|
|
1148
1156
|
return ProjectType.FULLSTACK_JS
|
|
1149
1157
|
return ProjectType.WEB_FRONTEND
|
|
1158
|
+
# Tauri: has src-tauri/
|
|
1159
|
+
if (result.root / "src-tauri").is_dir():
|
|
1160
|
+
return ProjectType.DESKTOP_TAURI
|
|
1150
1161
|
return ProjectType.FULLSTACK_JS
|
|
1151
1162
|
|
|
1163
|
+
# Data warehouse: dbt_project.yml is a strong signal
|
|
1164
|
+
if (result.root / "dbt_project.yml").exists():
|
|
1165
|
+
return ProjectType.DATA_WAREHOUSE
|
|
1166
|
+
# Kubernetes operator: Go + controllers/ dir
|
|
1167
|
+
if lang == "go" and (result.root / "controllers").is_dir():
|
|
1168
|
+
return ProjectType.KUBERNETES_OPERATOR
|
|
1169
|
+
# Serverless: serverless.yml or SAM template.yaml or wrangler.toml
|
|
1170
|
+
if (
|
|
1171
|
+
(result.root / "serverless.yml").exists()
|
|
1172
|
+
or (result.root / "serverless.yaml").exists()
|
|
1173
|
+
or (result.root / "wrangler.toml").exists()
|
|
1174
|
+
):
|
|
1175
|
+
return ProjectType.SERVERLESS
|
|
1152
1176
|
# Python types
|
|
1153
1177
|
if lang == "python":
|
|
1178
|
+
# Detect AI / agent project types from dependencies before build-system checks
|
|
1179
|
+
_req_text = ""
|
|
1180
|
+
for _rf in (
|
|
1181
|
+
result.root / "requirements.txt",
|
|
1182
|
+
result.root / "pyproject.toml",
|
|
1183
|
+
):
|
|
1184
|
+
if _rf.exists():
|
|
1185
|
+
_req_text += _rf.read_text(encoding="utf-8", errors="ignore").lower()
|
|
1186
|
+
_mcp_indicators = {"mcp", "model-context-protocol", "fastmcp", "modelcontextprotocol"}
|
|
1187
|
+
_agent_orch_indicators = {"autogen", "crewai", "langgraph", "swarm", "ag2", "pyautogen"}
|
|
1188
|
+
_llm_indicators = {
|
|
1189
|
+
"langchain",
|
|
1190
|
+
"llama-index",
|
|
1191
|
+
"llama_index",
|
|
1192
|
+
"haystack",
|
|
1193
|
+
"openai",
|
|
1194
|
+
"anthropic",
|
|
1195
|
+
"litellm",
|
|
1196
|
+
}
|
|
1197
|
+
_rag_indicators = {
|
|
1198
|
+
"chromadb",
|
|
1199
|
+
"faiss",
|
|
1200
|
+
"pinecone",
|
|
1201
|
+
"weaviate",
|
|
1202
|
+
"qdrant",
|
|
1203
|
+
"pgvector",
|
|
1204
|
+
"llama-index",
|
|
1205
|
+
}
|
|
1206
|
+
_mlops_indicators = {"mlflow", "bentoml", "ray", "kubeflow", "prefect", "airflow"}
|
|
1207
|
+
_streaming_indicators = {"kafka", "flink", "pyflink", "apache-beam", "pyspark"}
|
|
1208
|
+
if any(ind in _req_text for ind in _mcp_indicators):
|
|
1209
|
+
return ProjectType.MCP_SERVER
|
|
1210
|
+
if any(ind in _req_text for ind in _agent_orch_indicators):
|
|
1211
|
+
return ProjectType.AGENT_ORCHESTRATION
|
|
1212
|
+
if any(ind in _req_text for ind in _rag_indicators):
|
|
1213
|
+
return ProjectType.RAG_PIPELINE
|
|
1214
|
+
if any(ind in _req_text for ind in _mlops_indicators):
|
|
1215
|
+
return ProjectType.MLOPS_PLATFORM
|
|
1216
|
+
if any(ind in _req_text for ind in _streaming_indicators):
|
|
1217
|
+
return ProjectType.STREAMING_PIPELINE
|
|
1218
|
+
if any(ind in _req_text for ind in _llm_indicators):
|
|
1219
|
+
return ProjectType.LLM_APP
|
|
1154
1220
|
if build in ("pyproject", "setuptools"):
|
|
1155
1221
|
# Check for CLI entry point
|
|
1156
1222
|
if any("cli.py" in e for e in result.entry_points):
|