specsmith 0.21.0.dev765__tar.gz → 0.21.0.dev774__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.21.0.dev765/src/specsmith.egg-info → specsmith-0.21.0.dev774}/PKG-INFO +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/pyproject.toml +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/__init__.py +1 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/belief.py +3 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/certainty.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/failure_graph.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/recovery.py +14 -12
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/session.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/stress_tester.py +15 -13
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/trace.py +3 -3
- specsmith-0.21.0.dev774/src/specsmith/advanced_code_analysis.py +307 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/broker.py +13 -8
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/chat_runner.py +7 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/cleanup.py +165 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/context_seed.py +3 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/dispatch/dag.py +4 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/dispatch/dispatcher.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/dispatch/events.py +9 -9
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/endpoints.py +23 -16
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/events.py +9 -9
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/fallback.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/hf_leaderboard.py +4 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/indexer.py +9 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/llm_client.py +37 -7
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/mcp.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/memory.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/model_router.py +4 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/orchestrator.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/permissions.py +6 -5
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/profiles.py +7 -7
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/provider_registry.py +7 -7
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/repl.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/runner.py +15 -15
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/safety.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/spawner.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/token_pricing.py +2 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/tools.py +29 -14
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/voice.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/approvals.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/architect.py +12 -8
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/auditor.py +126 -68
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/auth.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/ci_manager.py +10 -9
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/cli.py +602 -382
- specsmith-0.21.0.dev774/src/specsmith/code_analysis.py +189 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/commands/intelligence.py +4 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/commands/issues_policy.py +21 -15
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/commands/reporting.py +6 -6
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/compliance/__init__.py +5 -5
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/compliance/_compat.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/compliance/checker.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/compliance/evidence.py +19 -19
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/compliance/reporter.py +5 -5
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/compressor.py +1 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/config.py +6 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/context_orchestrator.py +12 -9
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/context_window.py +4 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/credit_analyzer.py +7 -6
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/credits.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/dashboard.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/base.py +3 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/citations.py +6 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/fpd.py +6 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/patentsview.py +2 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/pfw.py +6 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/ppubs.py +2 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/ptab.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/differ.py +4 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/doctor.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/drive.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/editor.py +5 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/epistemic/__init__.py +10 -10
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/epistemic/belief.py +2 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/epistemic/certainty.py +3 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/epistemic/failure_graph.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/epistemic/recovery.py +14 -11
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/epistemic/stress_tester.py +15 -12
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/esdb/__init__.py +5 -5
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/esdb/_license.py +5 -6
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/esdb/bridge.py +12 -12
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/esdb/sqlite_store.py +7 -6
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/esdb_sweep.py +2 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/esdb_writer.py +7 -9
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/eval/runner.py +1 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/executor.py +3 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/exporter.py +4 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/governance_logic.py +34 -33
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/governance_store.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/governance_yaml.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/main_window.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/session_tab.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/widgets/chat_view.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/widgets/input_bar.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/worker.py +10 -7
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/history_search.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/importer.py +4 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/instinct.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/issue_reporter.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/local_model.py +18 -11
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/mcp_generator.py +5 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/mcp_server.py +12 -12
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/__init__.py +1 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m001_governance_yaml.py +14 -15
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m005_agent_run_tool.py +4 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m006_session_governance.py +4 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m009_esdb_first.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m010_post_esdb_cleanup.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/ollama_cmds.py +2 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/patent.py +3 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/phase.py +8 -7
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/plugins.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/policy.py +3 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/project_metrics.py +3 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/quality_report.py +14 -15
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/rate_limits.py +7 -5
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/requirements.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/requirements_parser.py +4 -6
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/retrieval.py +4 -4
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/safe_write.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/scaffolder.py +45 -45
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/serve.py +14 -13
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/session.py +12 -12
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/session_store.py +2 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/__init__.py +4 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills_builder.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/sync.py +14 -11
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/trace.py +4 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/transcripts.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/updater.py +9 -10
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/upgrader.py +7 -5
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/validator.py +17 -17
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/vcs/github.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/vcs_commands.py +6 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/wi_store.py +2 -2
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/wireframes.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/workspace.py +5 -5
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774/src/specsmith.egg-info}/PKG-INFO +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith.egg-info/SOURCES.txt +2 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/LICENSE +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/README.md +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/setup.cfg +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/epistemic/py.typed +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/__main__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/core.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/dispatch/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/dispatch/_status.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/dispatch/result.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/execution_profiles.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/hf_sync.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/model_intelligence.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/model_profiles.py +1 -1
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/router.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/rules.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/suggester.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/teams.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/terminal_env.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/agent/verifier.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/block_export.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/channel.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/commands/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/compliance/regulations.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/console_utils.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/datasources/odp.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/efficiency.py +3 -3
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/eval/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/eval/builtins.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/governed_pr.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/app.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/theme.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/widgets/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/widgets/provider_bar.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/widgets/token_meter.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/widgets/tool_panel.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/gui/widgets/update_checker.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/agent_skill.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/aider.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/base.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/claude_code.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/codity.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/copilot.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/cursor.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/gemini.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/warp.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/integrations/windsurf.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/languages.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/ledger.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m002_agents_slim.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m003_compliance_init.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m007_yaml_first.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/m008_esdb_full_coverage.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/migrations/runner.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/paths.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/profiles.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/recover.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/releaser.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/risk.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/session_init.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/ai_agents.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/cloud.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/corporate.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/cross_platform.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/data_engineering.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/devops.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/docs.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/embedded.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/governance.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/hardware.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/mobile.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/platform_engineering.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/productivity.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/software_engineering.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/specsmith_skills.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/ssh.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/skills/web_backend.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/agents.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/contributing.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/license-MIT.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/community/security.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/editorconfig.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/gitattributes.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/gitignore.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/go/go.mod.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/go/main.go.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/roles.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/rules.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/governance/verification.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/js/package.json.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/ledger.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/python/cli.py.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/python/init.py.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/readme.md.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/rust/main.rs.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/tool_installer.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/toolrules.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/tools.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/vcs/__init__.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/vcs/base.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/vcs/bitbucket.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith/vcs/gitlab.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith.egg-info/dependency_links.txt +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith.egg-info/entry_points.txt +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith.egg-info/requires.txt +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/src/specsmith.egg-info/top_level.txt +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_CMD_001.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_agent_profiles.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_agent_run_feedback.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_agent_runner_ready.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_ai_client.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_ai_intelligence.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_architect_interview.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_architect_v2.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_architecture.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_audit_governance.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_auditor.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_benchmark_harness.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_broker_scope.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_channel.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_chat_diff_decision.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_chat_runner_openai_compat.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_chat_stdin_protocol.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_cleanup_cmd.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_cli.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_cli_regressions.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_cli_workflows_history_drive.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_compliance.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_compliance_governance.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_compressor.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_deprecation_registry.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_dispatch.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_dual_write.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_e2e_nexus.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_efficiency.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_endpoints_cli.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_endpoints_store.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_epistemic.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_backend_switch.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_enforcement.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_integration.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_license.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_sqlite.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_status_integrity.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_status_output.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_sweep.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_verify_chain_cli.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_esdb_writer.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_fallback_chain.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_golden_path.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_importer.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_init_modes.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_integrations.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_integrations_codity.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_integrations_warp.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_intelligence.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_issue_policy_features.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_issue_reporter.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_issues_263_264.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_local_model.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_markdown_deprecation.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_mcp_client.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_mcp_server.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_metrics_flush.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_migration_direction.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_model_router.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_new_modules.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_nexus.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_parallel_agents.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_permissions.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_phase1_4_new.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_phase34_completion.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_project_metrics.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_quality_report.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_rate_limits.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_releaser.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_repl.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_repl_extended.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_reporting_commands.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_req_248_262.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_req_358_359.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_resume_command.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_scaffolder.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_schema_migrations.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_skill_marketplace.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_skills_mcp.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_smoke.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_sqlite_parity.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_suggester.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_sync_reconcile.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_terminal_env.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_token_cost.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_tools.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_trace_vault_esdb.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_typing_guardrails.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_validator.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_vcs.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_warp_parity.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_warp_parity_followup.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_wi_lifecycle.py +0 -0
- {specsmith-0.21.0.dev765 → specsmith-0.21.0.dev774}/tests/test_wi_lifecycle_extended.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specsmith
|
|
3
|
-
Version: 0.21.0.
|
|
3
|
+
Version: 0.21.0.dev774
|
|
4
4
|
Summary: AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, and Aider.
|
|
5
5
|
Author: Layer1Labs Silicon, Inc.
|
|
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.21.0.
|
|
7
|
+
version = "0.21.0.dev774"
|
|
8
8
|
description = "AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, and Aider."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -124,6 +124,7 @@ References
|
|
|
124
124
|
- ARE: https://github.com/organvm-i-theoria/auto-revision-epistemic-engine
|
|
125
125
|
- VERITAS: https://github.com/AionSystem/VERITAS
|
|
126
126
|
- Springer: https://doi.org/10.1007/s11948-023-00451-3
|
|
127
|
+
|
|
127
128
|
"""
|
|
128
129
|
|
|
129
130
|
from __future__ import annotations
|
|
@@ -45,6 +45,7 @@ References
|
|
|
45
45
|
- ARE framework: https://github.com/organvm-i-theoria/auto-revision-epistemic-engine
|
|
46
46
|
- VERITAS/CERTUS: https://github.com/AionSystem/VERITAS
|
|
47
47
|
- AI as Epistemic Technology (Springer): https://doi.org/10.1007/s11948-023-00451-3
|
|
48
|
+
|
|
48
49
|
"""
|
|
49
50
|
|
|
50
51
|
from __future__ import annotations
|
|
@@ -151,6 +152,7 @@ class BeliefArtifact:
|
|
|
151
152
|
confidence=ConfidenceLevel.LOW,
|
|
152
153
|
status=BeliefStatus.ACCEPTED,
|
|
153
154
|
)
|
|
155
|
+
|
|
154
156
|
"""
|
|
155
157
|
|
|
156
158
|
artifact_id: str
|
|
@@ -359,6 +361,6 @@ __all__ = [
|
|
|
359
361
|
"ConfidenceLevel",
|
|
360
362
|
"FailureMode",
|
|
361
363
|
"FailureSeverity",
|
|
362
|
-
"parse_requirements_as_beliefs",
|
|
363
364
|
"beliefs_from_dicts",
|
|
365
|
+
"parse_requirements_as_beliefs",
|
|
364
366
|
]
|
|
@@ -78,7 +78,7 @@ class CertaintyReport:
|
|
|
78
78
|
lines.append("Artifacts below threshold:")
|
|
79
79
|
for s in sorted(low, key=lambda x: x.propagated_score):
|
|
80
80
|
lines.append(
|
|
81
|
-
f" ✗ {s.artifact_id:25s} score={s.propagated_score:.2f} [{s.label}]"
|
|
81
|
+
f" ✗ {s.artifact_id:25s} score={s.propagated_score:.2f} [{s.label}]",
|
|
82
82
|
)
|
|
83
83
|
for note in s.notes[:2]:
|
|
84
84
|
lines.append(f" {note}")
|
|
@@ -196,4 +196,4 @@ class CertaintyEngine:
|
|
|
196
196
|
changed = True
|
|
197
197
|
|
|
198
198
|
|
|
199
|
-
__all__ = ["
|
|
199
|
+
__all__ = ["ArtifactCertainty", "CertaintyEngine", "CertaintyReport"]
|
|
@@ -89,7 +89,7 @@ class FailureModeGraph:
|
|
|
89
89
|
lines.append("=" * 50)
|
|
90
90
|
lines.append(
|
|
91
91
|
f"Equilibrium: {'✓ YES' if eq else '✗ NO'} | "
|
|
92
|
-
f"Nodes: {len(self._nodes)} | Logic Knots: {len(knots)}"
|
|
92
|
+
f"Nodes: {len(self._nodes)} | Logic Knots: {len(knots)}",
|
|
93
93
|
)
|
|
94
94
|
|
|
95
95
|
if knots:
|
|
@@ -128,8 +128,8 @@ class FailureModeGraph:
|
|
|
128
128
|
lines.append(f" style {_sid(node.artifact_id)} fill:#ff4444,color:#fff")
|
|
129
129
|
elif node.failure_count > 0:
|
|
130
130
|
lines.append(
|
|
131
|
-
f' {_sid(node.artifact_id)}["{label}\\n{node.failure_count} failures"]'
|
|
132
|
-
)
|
|
131
|
+
f' {_sid(node.artifact_id)}["{label}\\n{node.failure_count} failures"]',
|
|
132
|
+
)
|
|
133
133
|
lines.append(f" style {_sid(node.artifact_id)} fill:#ff9900,color:#000")
|
|
134
134
|
else:
|
|
135
135
|
lines.append(f' {_sid(node.artifact_id)}["{label}"]')
|
|
@@ -71,7 +71,9 @@ class RecoveryOperator:
|
|
|
71
71
|
return proposals
|
|
72
72
|
|
|
73
73
|
def _propose_for_failure(
|
|
74
|
-
self,
|
|
74
|
+
self,
|
|
75
|
+
artifact: BeliefArtifact,
|
|
76
|
+
fm: FailureMode,
|
|
75
77
|
) -> list[RecoveryProposal]:
|
|
76
78
|
challenge = fm.challenge.lower()
|
|
77
79
|
priority = _severity_priority(fm.severity)
|
|
@@ -90,9 +92,9 @@ class RecoveryOperator:
|
|
|
90
92
|
strategy=strategy,
|
|
91
93
|
description=f"Replace imprecise language in {artifact.artifact_id}.",
|
|
92
94
|
suggested_change=fm.recovery_hint
|
|
93
|
-
or "Replace vague terms with measurable criteria.",
|
|
95
|
+
or "Replace vague terms with measurable criteria.",
|
|
94
96
|
priority=priority,
|
|
95
|
-
)
|
|
97
|
+
),
|
|
96
98
|
)
|
|
97
99
|
elif "falsifiability" in challenge or "no test" in challenge:
|
|
98
100
|
proposals.append(
|
|
@@ -103,7 +105,7 @@ class RecoveryOperator:
|
|
|
103
105
|
description=f"Add a test for {artifact.artifact_id}.",
|
|
104
106
|
suggested_change=f"Add a test entry that covers: {artifact.source_text[:80]}",
|
|
105
107
|
priority=priority,
|
|
106
|
-
)
|
|
108
|
+
),
|
|
107
109
|
)
|
|
108
110
|
elif "observability" in challenge or "boundary" in challenge:
|
|
109
111
|
proposals.append(
|
|
@@ -114,7 +116,7 @@ class RecoveryOperator:
|
|
|
114
116
|
description=f"Add epistemic boundary to {artifact.artifact_id}.",
|
|
115
117
|
suggested_change="Declare scope, assumptions, and platform constraints.",
|
|
116
118
|
priority=priority,
|
|
117
|
-
)
|
|
119
|
+
),
|
|
118
120
|
)
|
|
119
121
|
if not artifact.propositions:
|
|
120
122
|
proposals.append(
|
|
@@ -125,7 +127,7 @@ class RecoveryOperator:
|
|
|
125
127
|
description=f"Add propositions to {artifact.artifact_id} — currently empty.", # noqa: E501
|
|
126
128
|
suggested_change="Add a description as a testable claim.",
|
|
127
129
|
priority=1,
|
|
128
|
-
)
|
|
130
|
+
),
|
|
129
131
|
)
|
|
130
132
|
elif "irreducibility" in challenge or "compound" in challenge:
|
|
131
133
|
proposals.append(
|
|
@@ -137,7 +139,7 @@ class RecoveryOperator:
|
|
|
137
139
|
suggested_change="Split into separate beliefs, each with a single proposition.",
|
|
138
140
|
estimated_cost="medium",
|
|
139
141
|
priority=priority,
|
|
140
|
-
)
|
|
142
|
+
),
|
|
141
143
|
)
|
|
142
144
|
elif "confidence" in challenge:
|
|
143
145
|
proposals.append(
|
|
@@ -149,7 +151,7 @@ class RecoveryOperator:
|
|
|
149
151
|
suggested_change="Add test coverage, evidence citations, and mark as stress-tested.", # noqa: E501
|
|
150
152
|
estimated_cost="medium",
|
|
151
153
|
priority=1,
|
|
152
|
-
)
|
|
154
|
+
),
|
|
153
155
|
)
|
|
154
156
|
|
|
155
157
|
return proposals
|
|
@@ -171,7 +173,7 @@ class RecoveryOperator:
|
|
|
171
173
|
description=f"Resolve duplicate ID conflict between {id1} and {id2}.",
|
|
172
174
|
suggested_change="Merge or rename one with a unique ID.",
|
|
173
175
|
priority=1,
|
|
174
|
-
)
|
|
176
|
+
),
|
|
175
177
|
]
|
|
176
178
|
return [
|
|
177
179
|
RecoveryProposal(
|
|
@@ -187,7 +189,7 @@ class RecoveryOperator:
|
|
|
187
189
|
),
|
|
188
190
|
estimated_cost="medium",
|
|
189
191
|
priority=1,
|
|
190
|
-
)
|
|
192
|
+
),
|
|
191
193
|
]
|
|
192
194
|
|
|
193
195
|
def format_proposals(self, proposals: list[RecoveryProposal]) -> str:
|
|
@@ -202,8 +204,8 @@ class RecoveryOperator:
|
|
|
202
204
|
]
|
|
203
205
|
for i, p in enumerate(proposals, 1):
|
|
204
206
|
lines.append(
|
|
205
|
-
f"{i}. [{p.strategy.value.upper()}] {p.artifact_id} (cost: {p.estimated_cost})"
|
|
206
|
-
)
|
|
207
|
+
f"{i}. [{p.strategy.value.upper()}] {p.artifact_id} (cost: {p.estimated_cost})",
|
|
208
|
+
)
|
|
207
209
|
lines.append(f" Problem: {p.failure_mode_challenge}")
|
|
208
210
|
lines.append(f" Action: {p.description}")
|
|
209
211
|
lines.append(f" Change: {p.suggested_change[:200]}")
|
|
@@ -149,7 +149,7 @@ class StressTester:
|
|
|
149
149
|
breakpoint=f"Proposition '{prop[:80]}' contains imprecise language.",
|
|
150
150
|
severity=FailureSeverity.MEDIUM,
|
|
151
151
|
recovery_hint="Replace vague terms with specific, measurable criteria.",
|
|
152
|
-
)
|
|
152
|
+
),
|
|
153
153
|
)
|
|
154
154
|
if _VAGUE_QUANTITY.search(prop):
|
|
155
155
|
fms.append(
|
|
@@ -159,7 +159,7 @@ class StressTester:
|
|
|
159
159
|
breakpoint=f"Proposition '{prop[:80]}' uses an unquantified quantity.",
|
|
160
160
|
severity=FailureSeverity.LOW,
|
|
161
161
|
recovery_hint="Replace with a specific numeric bound or threshold.",
|
|
162
|
-
)
|
|
162
|
+
),
|
|
163
163
|
)
|
|
164
164
|
return fms
|
|
165
165
|
|
|
@@ -178,7 +178,7 @@ class StressTester:
|
|
|
178
178
|
),
|
|
179
179
|
severity=FailureSeverity.HIGH,
|
|
180
180
|
recovery_hint="Add a test entry that covers this requirement.",
|
|
181
|
-
)
|
|
181
|
+
),
|
|
182
182
|
]
|
|
183
183
|
|
|
184
184
|
def _challenge_missing_boundary(self, artifact: BeliefArtifact) -> list[FailureMode]:
|
|
@@ -200,7 +200,7 @@ class StressTester:
|
|
|
200
200
|
),
|
|
201
201
|
severity=FailureSeverity.LOW,
|
|
202
202
|
recovery_hint="Add an explicit epistemic boundary declaring scope and assumptions.",
|
|
203
|
-
)
|
|
203
|
+
),
|
|
204
204
|
]
|
|
205
205
|
|
|
206
206
|
def _challenge_compound_claim(self, artifact: BeliefArtifact) -> list[FailureMode]:
|
|
@@ -215,7 +215,7 @@ class StressTester:
|
|
|
215
215
|
),
|
|
216
216
|
severity=FailureSeverity.LOW,
|
|
217
217
|
recovery_hint="Split into multiple, independently testable beliefs.",
|
|
218
|
-
)
|
|
218
|
+
),
|
|
219
219
|
]
|
|
220
220
|
for prop in artifact.propositions:
|
|
221
221
|
if _COMPOUND_INDICATORS.search(prop):
|
|
@@ -226,7 +226,7 @@ class StressTester:
|
|
|
226
226
|
breakpoint=f"Proposition '{prop[:80]}' contains multiple claims.",
|
|
227
227
|
severity=FailureSeverity.LOW,
|
|
228
228
|
recovery_hint="Decompose into separate propositions.",
|
|
229
|
-
)
|
|
229
|
+
),
|
|
230
230
|
]
|
|
231
231
|
return []
|
|
232
232
|
|
|
@@ -243,7 +243,7 @@ class StressTester:
|
|
|
243
243
|
),
|
|
244
244
|
severity=FailureSeverity.CRITICAL,
|
|
245
245
|
recovery_hint="Add a description or explicit propositions.",
|
|
246
|
-
)
|
|
246
|
+
),
|
|
247
247
|
]
|
|
248
248
|
|
|
249
249
|
def _challenge_p1_confidence(self, artifact: BeliefArtifact) -> list[FailureMode]:
|
|
@@ -261,11 +261,13 @@ class StressTester:
|
|
|
261
261
|
),
|
|
262
262
|
severity=FailureSeverity.CRITICAL,
|
|
263
263
|
recovery_hint="Stress-test, add evidence, or lower the priority.",
|
|
264
|
-
)
|
|
264
|
+
),
|
|
265
265
|
]
|
|
266
266
|
|
|
267
267
|
def _challenge_circular_links(
|
|
268
|
-
self,
|
|
268
|
+
self,
|
|
269
|
+
artifact: BeliefArtifact,
|
|
270
|
+
id_set: set[str],
|
|
269
271
|
) -> list[FailureMode]:
|
|
270
272
|
fms = []
|
|
271
273
|
for link in artifact.inferential_links:
|
|
@@ -277,7 +279,7 @@ class StressTester:
|
|
|
277
279
|
breakpoint=f"{artifact.artifact_id} references '{link}' which does not exist.", # noqa: E501
|
|
278
280
|
severity=FailureSeverity.MEDIUM,
|
|
279
281
|
recovery_hint=f"Remove or correct the link to '{link}'.",
|
|
280
|
-
)
|
|
282
|
+
),
|
|
281
283
|
)
|
|
282
284
|
return fms
|
|
283
285
|
|
|
@@ -293,7 +295,7 @@ class StressTester:
|
|
|
293
295
|
a.artifact_id,
|
|
294
296
|
seen[a.artifact_id],
|
|
295
297
|
"Duplicate belief ID — two accepted beliefs share the same identifier.",
|
|
296
|
-
)
|
|
298
|
+
),
|
|
297
299
|
)
|
|
298
300
|
seen[a.artifact_id] = a.artifact_id
|
|
299
301
|
|
|
@@ -312,7 +314,7 @@ class StressTester:
|
|
|
312
314
|
a1.artifact_id,
|
|
313
315
|
a2.artifact_id,
|
|
314
316
|
f"Negation conflict in '{comp}': contradictory MUST/MUST NOT claims.", # noqa: E501
|
|
315
|
-
)
|
|
317
|
+
),
|
|
316
318
|
)
|
|
317
319
|
return knots
|
|
318
320
|
|
|
@@ -352,4 +354,4 @@ def _extract_covered_reqs(test_path: Path) -> set[str]:
|
|
|
352
354
|
return set(pattern.findall(content))
|
|
353
355
|
|
|
354
356
|
|
|
355
|
-
__all__ = ["
|
|
357
|
+
__all__ = ["StressTestResult", "StressTester"]
|
|
@@ -142,13 +142,13 @@ class TraceVault:
|
|
|
142
142
|
expected_content_hash = _sha256(expected_content)
|
|
143
143
|
if rec.content_hash != expected_content_hash:
|
|
144
144
|
errors.append(
|
|
145
|
-
f"{rec.seal_id}: content_hash invalid — description or metadata tampered"
|
|
145
|
+
f"{rec.seal_id}: content_hash invalid — description or metadata tampered",
|
|
146
146
|
)
|
|
147
147
|
# Verify entry_hash
|
|
148
148
|
expected_entry = _sha256(f"{rec.content_hash}:{rec.prev_hash}")
|
|
149
149
|
if rec.entry_hash != expected_entry:
|
|
150
150
|
errors.append(
|
|
151
|
-
f"{rec.seal_id}: entry_hash invalid — record may have been tampered with"
|
|
151
|
+
f"{rec.seal_id}: entry_hash invalid — record may have been tampered with",
|
|
152
152
|
)
|
|
153
153
|
# Verify chain link
|
|
154
154
|
if rec.prev_hash != prev_hash:
|
|
@@ -206,4 +206,4 @@ def _sha256(text: str) -> str:
|
|
|
206
206
|
return hashlib.sha256(text.encode("utf-8")).hexdigest()
|
|
207
207
|
|
|
208
208
|
|
|
209
|
-
__all__ = ["
|
|
209
|
+
__all__ = ["SealRecord", "SealType", "TraceVault"]
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
+
"""Advanced code analysis framework for specsmith with AI-assisted features."""
|
|
4
|
+
|
|
5
|
+
import ast
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from specsmith.auditor import AuditResult
|
|
11
|
+
from specsmith.code_analysis import ComplexityReport
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class RefactoringSuggestion:
|
|
16
|
+
"""A suggestion for code refactoring."""
|
|
17
|
+
|
|
18
|
+
file_path: str
|
|
19
|
+
line_number: int
|
|
20
|
+
suggestion_type: str
|
|
21
|
+
description: str
|
|
22
|
+
severity: str # 'low', 'medium', 'high', 'critical'
|
|
23
|
+
confidence: float # 0.0 to 1.0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class AIAssistedAnalysis:
|
|
28
|
+
"""AI-assisted code analysis results."""
|
|
29
|
+
|
|
30
|
+
file_path: str
|
|
31
|
+
suggestions: list[RefactoringSuggestion]
|
|
32
|
+
code_quality_score: float
|
|
33
|
+
complexity_trend: str # 'improving', 'stable', 'regressing'
|
|
34
|
+
improvement_potential: float # 0.0 to 1.0
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class AdvancedCodeAnalyzer:
|
|
38
|
+
"""Advanced code analysis engine with AI-assisted features."""
|
|
39
|
+
|
|
40
|
+
def __init__(self) -> None:
|
|
41
|
+
self.complexity_threshold = 10 # A-range complexity threshold
|
|
42
|
+
|
|
43
|
+
def analyze_file_for_refactoring(self, file_path: Path) -> list[RefactoringSuggestion]:
|
|
44
|
+
"""Analyze a file for potential refactoring opportunities."""
|
|
45
|
+
suggestions: list[RefactoringSuggestion] = []
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
with open(file_path, encoding="utf-8") as f:
|
|
49
|
+
content = f.read()
|
|
50
|
+
|
|
51
|
+
# Parse the file with AST
|
|
52
|
+
tree = ast.parse(content)
|
|
53
|
+
|
|
54
|
+
# Check for long functions (potential candidates for refactoring)
|
|
55
|
+
for node in ast.walk(tree):
|
|
56
|
+
if isinstance(node, ast.FunctionDef):
|
|
57
|
+
# Calculate function length
|
|
58
|
+
if hasattr(node, "body"):
|
|
59
|
+
lines = node.body
|
|
60
|
+
if len(lines) > 20: # Arbitrary threshold for long functions
|
|
61
|
+
description = (
|
|
62
|
+
f"Function '{node.name}' has {len(lines)} lines - "
|
|
63
|
+
"consider refactoring"
|
|
64
|
+
)
|
|
65
|
+
suggestions.append(
|
|
66
|
+
RefactoringSuggestion(
|
|
67
|
+
file_path=str(file_path),
|
|
68
|
+
line_number=node.lineno,
|
|
69
|
+
suggestion_type="function_length",
|
|
70
|
+
description=description,
|
|
71
|
+
severity="medium",
|
|
72
|
+
confidence=0.7,
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Check for complex conditionals
|
|
77
|
+
complex_conditions = self._find_complex_conditions(node)
|
|
78
|
+
for condition in complex_conditions:
|
|
79
|
+
description = (
|
|
80
|
+
f"Complex conditional at line {condition['line']} - "
|
|
81
|
+
"consider simplification"
|
|
82
|
+
)
|
|
83
|
+
suggestions.append(
|
|
84
|
+
RefactoringSuggestion(
|
|
85
|
+
file_path=str(file_path),
|
|
86
|
+
line_number=condition["line"],
|
|
87
|
+
suggestion_type="conditional_complexity",
|
|
88
|
+
description=description,
|
|
89
|
+
severity="high",
|
|
90
|
+
confidence=0.8,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
except Exception:
|
|
95
|
+
# Silently ignore parsing errors for now
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
return suggestions
|
|
99
|
+
|
|
100
|
+
def _find_complex_conditions(self, node: ast.AST) -> list[dict[str, Any]]:
|
|
101
|
+
"""Find complex conditional statements."""
|
|
102
|
+
conditions: list[dict[str, Any]] = []
|
|
103
|
+
if isinstance(node, ast.If) and isinstance(node.test, ast.BoolOp):
|
|
104
|
+
# Check for nested if statements or complex boolean expressions
|
|
105
|
+
# Count the number of operations in boolean expressions
|
|
106
|
+
bool_op = node.test
|
|
107
|
+
if len(bool_op.values) > 3: # More than 3 operands is complex
|
|
108
|
+
conditions.append(
|
|
109
|
+
{
|
|
110
|
+
"line": node.lineno,
|
|
111
|
+
"type": "boolean_expression",
|
|
112
|
+
"complexity": len(bool_op.values),
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
return conditions
|
|
116
|
+
|
|
117
|
+
def analyze_codebase_for_ai_assistance(self, root: Path) -> dict[str, AIAssistedAnalysis]:
|
|
118
|
+
"""Analyze entire codebase for AI-assisted insights."""
|
|
119
|
+
results = {}
|
|
120
|
+
|
|
121
|
+
# Analyze Python files
|
|
122
|
+
for py_file in root.rglob("*.py"):
|
|
123
|
+
# Skip test files and hidden directories
|
|
124
|
+
if "test" in str(py_file) or any(part.startswith(".") for part in py_file.parts):
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
# Get complexity report
|
|
128
|
+
complexity_reports = self._analyze_file_complexity(py_file)
|
|
129
|
+
|
|
130
|
+
# Get refactoring suggestions
|
|
131
|
+
suggestions = self.analyze_file_for_refactoring(py_file)
|
|
132
|
+
|
|
133
|
+
# Calculate quality score
|
|
134
|
+
quality_score = self._calculate_quality_score(complexity_reports, suggestions)
|
|
135
|
+
|
|
136
|
+
# Determine complexity trend (simplified)
|
|
137
|
+
complexity_trend = self._determine_complexity_trend(complexity_reports)
|
|
138
|
+
|
|
139
|
+
results[str(py_file)] = AIAssistedAnalysis(
|
|
140
|
+
file_path=str(py_file),
|
|
141
|
+
suggestions=suggestions,
|
|
142
|
+
code_quality_score=quality_score,
|
|
143
|
+
complexity_trend=complexity_trend,
|
|
144
|
+
improvement_potential=self._calculate_improvement_potential(suggestions),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return results
|
|
148
|
+
|
|
149
|
+
def _analyze_file_complexity(self, file_path: Path) -> list[ComplexityReport]:
|
|
150
|
+
"""Analyze complexity of a single file."""
|
|
151
|
+
# This would use the existing functionality from code_analysis.py
|
|
152
|
+
# For now, we'll create a simplified version
|
|
153
|
+
reports = []
|
|
154
|
+
try:
|
|
155
|
+
with open(file_path, encoding="utf-8") as f:
|
|
156
|
+
content = f.read()
|
|
157
|
+
|
|
158
|
+
tree = ast.parse(content)
|
|
159
|
+
|
|
160
|
+
# Walk through the AST to find function definitions
|
|
161
|
+
for node in ast.walk(tree):
|
|
162
|
+
if isinstance(node, ast.FunctionDef):
|
|
163
|
+
complexity = self._calculate_complexity(node)
|
|
164
|
+
if complexity > self.complexity_threshold:
|
|
165
|
+
reports.append(
|
|
166
|
+
ComplexityReport(
|
|
167
|
+
file_path=str(file_path),
|
|
168
|
+
function_name=node.name,
|
|
169
|
+
complexity=complexity,
|
|
170
|
+
line_number=node.lineno,
|
|
171
|
+
message=(
|
|
172
|
+
f"Function '{node.name}' has cyclomatic complexity of "
|
|
173
|
+
f"{complexity}"
|
|
174
|
+
),
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
except Exception:
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
return reports
|
|
181
|
+
|
|
182
|
+
def _calculate_complexity(self, node: ast.AST) -> int:
|
|
183
|
+
"""Calculate cyclomatic complexity of an AST node."""
|
|
184
|
+
complexity = 1 # Base complexity
|
|
185
|
+
|
|
186
|
+
# Count control flow statements
|
|
187
|
+
for child in ast.iter_child_nodes(node):
|
|
188
|
+
if isinstance(child, (ast.If, ast.While, ast.For, ast.With, ast.Try)):
|
|
189
|
+
complexity += 1
|
|
190
|
+
elif isinstance(child, ast.BoolOp):
|
|
191
|
+
complexity += len(child.values) - 1
|
|
192
|
+
elif isinstance(child, ast.Compare):
|
|
193
|
+
complexity += len(child.comparators) - 1
|
|
194
|
+
elif isinstance(child, ast.ExceptHandler):
|
|
195
|
+
complexity += 1
|
|
196
|
+
|
|
197
|
+
# Recursively check children
|
|
198
|
+
complexity += self._calculate_complexity(child)
|
|
199
|
+
|
|
200
|
+
return complexity
|
|
201
|
+
|
|
202
|
+
def _calculate_quality_score(
|
|
203
|
+
self, complexity_reports: list[ComplexityReport], suggestions: list[RefactoringSuggestion]
|
|
204
|
+
) -> float:
|
|
205
|
+
"""Calculate overall code quality score."""
|
|
206
|
+
# Base score is 100
|
|
207
|
+
score = 100.0
|
|
208
|
+
|
|
209
|
+
# Deduct points for high complexity
|
|
210
|
+
high_complexity_count = len([r for r in complexity_reports if r.complexity > 10])
|
|
211
|
+
score -= high_complexity_count * 5
|
|
212
|
+
|
|
213
|
+
# Deduct points for refactoring suggestions
|
|
214
|
+
score -= len(suggestions) * 2
|
|
215
|
+
|
|
216
|
+
# Ensure score is within bounds
|
|
217
|
+
return max(0, min(100, score))
|
|
218
|
+
|
|
219
|
+
def _determine_complexity_trend(self, complexity_reports: list[ComplexityReport]) -> str:
|
|
220
|
+
"""Determine if complexity is improving, stable, or regressing."""
|
|
221
|
+
if not complexity_reports:
|
|
222
|
+
return "stable"
|
|
223
|
+
|
|
224
|
+
# Simplified logic - in a real implementation, this would compare with historical data
|
|
225
|
+
high_complexity = [r for r in complexity_reports if r.complexity > 10]
|
|
226
|
+
if len(high_complexity) > 0:
|
|
227
|
+
return "regressing"
|
|
228
|
+
return "stable"
|
|
229
|
+
|
|
230
|
+
def _calculate_improvement_potential(self, suggestions: list[RefactoringSuggestion]) -> float:
|
|
231
|
+
"""Calculate potential improvement based on suggestions."""
|
|
232
|
+
if not suggestions:
|
|
233
|
+
return 0.0
|
|
234
|
+
|
|
235
|
+
# Weight suggestions by severity
|
|
236
|
+
severity_weights = {
|
|
237
|
+
"low": 0.2,
|
|
238
|
+
"medium": 0.5,
|
|
239
|
+
"high": 0.8,
|
|
240
|
+
"critical": 1.0,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
total_weight = sum(severity_weights.get(s.suggestion_type, 0.5) for s in suggestions)
|
|
244
|
+
return min(1.0, total_weight / len(suggestions) if suggestions else 0)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def create_ai_assisted_code_report(root: Path) -> dict[str, AIAssistedAnalysis]:
|
|
248
|
+
"""Create an AI-assisted code quality report."""
|
|
249
|
+
analyzer = AdvancedCodeAnalyzer()
|
|
250
|
+
return analyzer.analyze_codebase_for_ai_assistance(root)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def generate_refactoring_report(root: Path) -> dict[str, list[RefactoringSuggestion]]:
|
|
254
|
+
"""Generate a comprehensive refactoring report."""
|
|
255
|
+
analyzer = AdvancedCodeAnalyzer()
|
|
256
|
+
report = {}
|
|
257
|
+
|
|
258
|
+
# Analyze Python files
|
|
259
|
+
for py_file in root.rglob("*.py"):
|
|
260
|
+
# Skip test files and hidden directories
|
|
261
|
+
if "test" in str(py_file) or any(part.startswith(".") for part in py_file.parts):
|
|
262
|
+
continue
|
|
263
|
+
|
|
264
|
+
suggestions = analyzer.analyze_file_for_refactoring(py_file)
|
|
265
|
+
report[str(py_file)] = suggestions
|
|
266
|
+
|
|
267
|
+
return report
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def get_ai_assisted_analysis(root: Path) -> dict[str, AIAssistedAnalysis]:
|
|
271
|
+
"""Get AI-assisted analysis for all files."""
|
|
272
|
+
return create_ai_assisted_code_report(root)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def check_ai_compliance(root: Path) -> list[AuditResult]:
|
|
276
|
+
"""Check AI compliance based on the analysis."""
|
|
277
|
+
issues = []
|
|
278
|
+
|
|
279
|
+
# Check if we have AI-assisted analysis capabilities
|
|
280
|
+
try:
|
|
281
|
+
analysis = get_ai_assisted_analysis(root)
|
|
282
|
+
if analysis:
|
|
283
|
+
issues.append(
|
|
284
|
+
AuditResult(
|
|
285
|
+
name="ai-assisted-analysis",
|
|
286
|
+
passed=True,
|
|
287
|
+
message="AI-assisted code analysis capabilities are available",
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
else:
|
|
291
|
+
issues.append(
|
|
292
|
+
AuditResult(
|
|
293
|
+
name="ai-assisted-analysis",
|
|
294
|
+
passed=False,
|
|
295
|
+
message="AI-assisted code analysis capabilities are not available",
|
|
296
|
+
)
|
|
297
|
+
)
|
|
298
|
+
except Exception as e:
|
|
299
|
+
issues.append(
|
|
300
|
+
AuditResult(
|
|
301
|
+
name="ai-assisted-analysis",
|
|
302
|
+
passed=False,
|
|
303
|
+
message=f"Error checking AI compliance: {e!s}",
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
return issues
|