specsmith 0.20.1.dev749__tar.gz → 0.20.1.dev759__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.20.1.dev749/src/specsmith.egg-info → specsmith-0.20.1.dev759}/PKG-INFO +15 -1
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/README.md +14 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/pyproject.toml +1 -1
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/runner.py +12 -0
- specsmith-0.20.1.dev759/src/specsmith/agent/terminal_env.py +119 -0
- specsmith-0.20.1.dev759/src/specsmith/integrations/warp.py +179 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759/src/specsmith.egg-info}/PKG-INFO +15 -1
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_integrations_warp.py +24 -0
- specsmith-0.20.1.dev759/tests/test_terminal_env.py +137 -0
- specsmith-0.20.1.dev749/src/specsmith/agent/terminal_env.py +0 -43
- specsmith-0.20.1.dev749/src/specsmith/integrations/warp.py +0 -84
- specsmith-0.20.1.dev749/tests/test_terminal_env.py +0 -58
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/LICENSE +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/setup.cfg +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/belief.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/certainty.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/failure_graph.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/py.typed +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/recovery.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/session.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/stress_tester.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/epistemic/trace.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/__main__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/broker.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/chat_runner.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/cleanup.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/context_seed.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/core.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/dispatch/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/dispatch/_status.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/dispatch/dag.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/dispatch/events.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/dispatch/result.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/endpoints.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/events.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/execution_profiles.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/fallback.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/hf_leaderboard.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/hf_sync.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/indexer.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/llm_client.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/mcp.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/memory.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/model_intelligence.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/model_profiles.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/model_router.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/orchestrator.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/permissions.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/profiles.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/provider_registry.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/repl.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/router.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/rules.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/safety.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/spawner.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/suggester.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/teams.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/token_pricing.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/tools.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/verifier.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/agent/voice.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/approvals.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/architect.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/auditor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/auth.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/block_export.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/channel.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/ci_manager.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/cli.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/commands/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/commands/intelligence.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/commands/issues_policy.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/commands/reporting.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/compliance/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/compliance/_compat.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/compliance/checker.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/compliance/evidence.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/compliance/regulations.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/compliance/reporter.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/compressor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/config.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/console_utils.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/context_orchestrator.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/context_window.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/credit_analyzer.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/credits.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/dashboard.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/base.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/citations.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/fpd.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/odp.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/patentsview.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/pfw.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/ppubs.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/datasources/ptab.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/differ.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/doctor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/drive.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/editor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/efficiency.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/epistemic/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/epistemic/belief.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/epistemic/certainty.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/epistemic/failure_graph.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/epistemic/recovery.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/epistemic/stress_tester.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/esdb/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/esdb/_license.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/esdb/bridge.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/esdb/sqlite_store.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/esdb_sweep.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/esdb_writer.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/eval/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/eval/builtins.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/eval/runner.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/executor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/exporter.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/governance_logic.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/governance_store.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/governance_yaml.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/governed_pr.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/app.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/main_window.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/session_tab.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/theme.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/widgets/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/widgets/chat_view.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/widgets/input_bar.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/widgets/provider_bar.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/widgets/token_meter.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/widgets/tool_panel.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/widgets/update_checker.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/gui/worker.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/history_search.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/importer.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/instinct.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/agent_skill.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/aider.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/base.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/claude_code.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/codity.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/copilot.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/cursor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/gemini.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/integrations/windsurf.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/issue_reporter.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/languages.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/ledger.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/local_model.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/mcp_generator.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/mcp_server.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m002_agents_slim.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m003_compliance_init.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m006_session_governance.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m007_yaml_first.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m008_esdb_full_coverage.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m009_esdb_first.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/m010_post_esdb_cleanup.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/migrations/runner.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/ollama_cmds.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/patent.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/paths.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/phase.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/plugins.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/policy.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/profiles.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/project_metrics.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/quality_report.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/rate_limits.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/recover.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/releaser.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/requirements.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/requirements_parser.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/retrieval.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/risk.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/safe_write.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/scaffolder.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/serve.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/session.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/session_init.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/session_store.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/ai_agents.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/cloud.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/corporate.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/cross_platform.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/data_engineering.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/devops.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/docs.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/embedded.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/governance.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/hardware.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/mobile.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/platform_engineering.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/productivity.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/software_engineering.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/specsmith_skills.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/ssh.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills/web_backend.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/skills_builder.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/sync.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/agents.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/contributing.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/license-MIT.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/community/security.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/editorconfig.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/gitattributes.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/gitignore.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/go/go.mod.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/go/main.go.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/roles.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/rules.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/governance/verification.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/js/package.json.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/ledger.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/python/cli.py.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/python/init.py.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/readme.md.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/rust/main.rs.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/tool_installer.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/toolrules.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/tools.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/trace.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/transcripts.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/updater.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/upgrader.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/validator.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/vcs/__init__.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/vcs/base.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/vcs/bitbucket.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/vcs/github.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/vcs/gitlab.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/vcs_commands.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/wi_store.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/wireframes.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith/workspace.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith.egg-info/SOURCES.txt +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith.egg-info/dependency_links.txt +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith.egg-info/entry_points.txt +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith.egg-info/requires.txt +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/src/specsmith.egg-info/top_level.txt +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_CMD_001.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_agent_profiles.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_agent_run_feedback.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_agent_runner_ready.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_ai_client.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_ai_intelligence.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_architect_interview.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_architect_v2.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_architecture.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_audit_governance.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_auditor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_benchmark_harness.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_broker_scope.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_channel.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_chat_diff_decision.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_chat_runner_openai_compat.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_chat_stdin_protocol.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_cleanup_cmd.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_cli.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_cli_regressions.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_cli_workflows_history_drive.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_compliance.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_compliance_governance.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_compressor.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_deprecation_registry.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_dispatch.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_dual_write.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_e2e_nexus.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_efficiency.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_endpoints_cli.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_endpoints_store.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_epistemic.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_backend_switch.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_enforcement.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_integration.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_license.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_sqlite.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_status_integrity.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_status_output.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_sweep.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_verify_chain_cli.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_esdb_writer.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_fallback_chain.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_golden_path.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_importer.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_init_modes.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_integrations.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_integrations_codity.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_intelligence.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_issue_policy_features.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_issue_reporter.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_issues_263_264.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_local_model.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_markdown_deprecation.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_mcp_client.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_mcp_server.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_metrics_flush.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_migration_direction.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_model_router.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_new_modules.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_nexus.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_parallel_agents.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_permissions.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_phase1_4_new.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_phase34_completion.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_project_metrics.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_quality_report.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_rate_limits.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_releaser.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_repl.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_repl_extended.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_reporting_commands.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_req_248_262.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_req_358_359.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_resume_command.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_scaffolder.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_schema_migrations.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_skill_marketplace.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_skills_mcp.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_smoke.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_sqlite_parity.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_suggester.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_sync_reconcile.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_token_cost.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_tools.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_trace_vault_esdb.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_typing_guardrails.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_validator.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_vcs.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_warp_parity.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_warp_parity_followup.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/tests/test_wi_lifecycle.py +0 -0
- {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev759}/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.20.1.
|
|
3
|
+
Version: 0.20.1.dev759
|
|
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
|
|
@@ -1341,6 +1341,20 @@ oz agent run --mcp '{"specsmith-governance": {"command": "specsmith", "args": ["
|
|
|
1341
1341
|
| `governance_req_list` | All requirements with status + test coverage, filterable |
|
|
1342
1342
|
| `governance_trace_seal` | Create a cryptographic trace vault seal |
|
|
1343
1343
|
|
|
1344
|
+
### Third-party CLI agent toolbar
|
|
1345
|
+
|
|
1346
|
+
For **specsmith** and **aider** (not yet natively supported by Warp), add this regex once in **Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar**:
|
|
1347
|
+
|
|
1348
|
+
```
|
|
1349
|
+
specsmith\s+run|aider
|
|
1350
|
+
```
|
|
1351
|
+
|
|
1352
|
+
`claude`, `codex`, `gemini`, and `cursor` are already natively supported — no regex needed.
|
|
1353
|
+
|
|
1354
|
+
Once set, the toolbelt (Rich Input, attach code, File Explorer, Tab Configs, Remote Control) appears whenever `specsmith run` or `aider` is running. `specsmith run` also emits an OSC 9 desktop notification on session start — intercepted automatically by Warp, iTerm2, and Windows Terminal.
|
|
1355
|
+
|
|
1356
|
+
Run `specsmith integrate warp` to regenerate `.warp/SETUP.md` with the full per-REPL setup guide.
|
|
1357
|
+
|
|
1344
1358
|
### Repository Workflows (Ctrl+Shift+R)
|
|
1345
1359
|
|
|
1346
1360
|
Clone this repo and open it in Warp — seven governance workflows appear automatically in
|
|
@@ -1263,6 +1263,20 @@ oz agent run --mcp '{"specsmith-governance": {"command": "specsmith", "args": ["
|
|
|
1263
1263
|
| `governance_req_list` | All requirements with status + test coverage, filterable |
|
|
1264
1264
|
| `governance_trace_seal` | Create a cryptographic trace vault seal |
|
|
1265
1265
|
|
|
1266
|
+
### Third-party CLI agent toolbar
|
|
1267
|
+
|
|
1268
|
+
For **specsmith** and **aider** (not yet natively supported by Warp), add this regex once in **Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar**:
|
|
1269
|
+
|
|
1270
|
+
```
|
|
1271
|
+
specsmith\s+run|aider
|
|
1272
|
+
```
|
|
1273
|
+
|
|
1274
|
+
`claude`, `codex`, `gemini`, and `cursor` are already natively supported — no regex needed.
|
|
1275
|
+
|
|
1276
|
+
Once set, the toolbelt (Rich Input, attach code, File Explorer, Tab Configs, Remote Control) appears whenever `specsmith run` or `aider` is running. `specsmith run` also emits an OSC 9 desktop notification on session start — intercepted automatically by Warp, iTerm2, and Windows Terminal.
|
|
1277
|
+
|
|
1278
|
+
Run `specsmith integrate warp` to regenerate `.warp/SETUP.md` with the full per-REPL setup guide.
|
|
1279
|
+
|
|
1266
1280
|
### Repository Workflows (Ctrl+Shift+R)
|
|
1267
1281
|
|
|
1268
1282
|
Clone this repo and open it in Warp — seven governance workflows appear automatically in
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specsmith"
|
|
7
|
-
version = "0.20.1.
|
|
7
|
+
version = "0.20.1.dev759"
|
|
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"
|
|
@@ -306,6 +306,13 @@ class AgentRunner:
|
|
|
306
306
|
|
|
307
307
|
# Host-terminal detection (REQ-444): when running inside Warp the
|
|
308
308
|
# banner/ready frame advertises native integration. Read-only.
|
|
309
|
+
# Set SPECSMITH_RUN_ACTIVE so any child specsmith command (audit,
|
|
310
|
+
# preflight, checkpoint, etc.) can detect they are running inside
|
|
311
|
+
# the Nexus REPL and report context-aware governance notifications.
|
|
312
|
+
import os as _os_init
|
|
313
|
+
|
|
314
|
+
_os_init.environ.setdefault("SPECSMITH_RUN_ACTIVE", "1")
|
|
315
|
+
|
|
309
316
|
from specsmith.agent.terminal_env import detect_terminal
|
|
310
317
|
|
|
311
318
|
self.terminal = detect_terminal()
|
|
@@ -395,6 +402,11 @@ class AgentRunner:
|
|
|
395
402
|
if self.terminal.is_warp:
|
|
396
403
|
ver = f" {self.terminal.version}" if self.terminal.version else ""
|
|
397
404
|
lines.insert(3, f" terminal: Warp{ver} \u2014 native integration active")
|
|
405
|
+
# Emit OSC 9 desktop notification so Warp surfaces a popup.
|
|
406
|
+
from specsmith.agent.terminal_env import emit_warp_notification
|
|
407
|
+
|
|
408
|
+
proj = Path(self.project_dir).name
|
|
409
|
+
emit_warp_notification(f"specsmith run | {proj} | governance active")
|
|
398
410
|
for s in statuses:
|
|
399
411
|
if s.available:
|
|
400
412
|
lines.append(
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
+
"""Terminal-environment detection for specsmith (REQ-444).
|
|
4
|
+
|
|
5
|
+
Lets the interactive REPL (``specsmith run``) and standalone CLI commands
|
|
6
|
+
detect when they are running inside Warp and which CLI agent REPL is active.
|
|
7
|
+
Detection is based on:
|
|
8
|
+
* ``TERM_PROGRAM=WarpTerminal`` / any ``WARP_*`` env var — Warp host
|
|
9
|
+
* ``SPECSMITH_RUN_ACTIVE=1`` — set by ``specsmith run`` on REPL start
|
|
10
|
+
* ``AIDER_MODEL`` / ``AIDER_CONFIG`` — set by aider at session start
|
|
11
|
+
* ``CLAUDE_CODE_ENTRYPOINT`` — set by Claude Code CLI
|
|
12
|
+
* ``CODEX_CLI_SESSION`` — set by OpenAI Codex CLI
|
|
13
|
+
* ``GEMINI_CLI`` — set by Gemini CLI
|
|
14
|
+
* ``CURSOR_TRACE_ID`` — set by Cursor CLI
|
|
15
|
+
|
|
16
|
+
All detection is read-only and purely best-effort.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
from dataclasses import asdict, dataclass
|
|
24
|
+
from typing import TextIO
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Known CLI-agent env-var signals.
|
|
28
|
+
# Keys are canonical agent IDs; values are lists of env vars that
|
|
29
|
+
# confirm the agent is (or recently was) active in this shell session.
|
|
30
|
+
# Warp natively supports: claude, codex, gemini, cursor.
|
|
31
|
+
# specsmith and aider are NOT natively supported — users add them via the
|
|
32
|
+
# custom toolbar regex in Warp Settings → Agents → Third party CLI agents.
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
_AGENT_ENV_SIGNALS: dict[str, list[str]] = {
|
|
35
|
+
"specsmith": ["SPECSMITH_RUN_ACTIVE"],
|
|
36
|
+
"aider": ["AIDER_MODEL", "AIDER_CONFIG", "AIDER_CHAT_LANGUAGE"],
|
|
37
|
+
"claude": ["CLAUDE_CODE_ENTRYPOINT", "ANTHROPIC_CLAUDE_CODE_SESSION"],
|
|
38
|
+
"codex": ["CODEX_CLI_SESSION", "OPENAI_CODEX_CLI"],
|
|
39
|
+
"gemini": ["GEMINI_CLI", "GEMINI_CLI_SESSION"],
|
|
40
|
+
"cursor": ["CURSOR_TRACE_ID", "CURSOR_SESSION_ID"],
|
|
41
|
+
"copilot": ["GITHUB_COPILOT_CLI", "GH_COPILOT_SESSION"],
|
|
42
|
+
"windsurf": ["WINDSURF_SESSION", "CODEIUM_SESSION"],
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class TerminalInfo:
|
|
48
|
+
"""Information about the host terminal and active CLI agent REPL."""
|
|
49
|
+
|
|
50
|
+
is_warp: bool
|
|
51
|
+
program: str
|
|
52
|
+
version: str
|
|
53
|
+
#: Canonical agent ID when a known CLI agent REPL is detected, else "".
|
|
54
|
+
#: Examples: ``"specsmith"``, ``"aider"``, ``"claude"``, ``"codex"``.
|
|
55
|
+
active_agent: str = ""
|
|
56
|
+
|
|
57
|
+
def as_dict(self) -> dict[str, object]:
|
|
58
|
+
"""Return a flat dict suitable for the ``ready`` event frame."""
|
|
59
|
+
return asdict(self)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def detect_terminal(env: dict[str, str] | None = None) -> TerminalInfo:
|
|
63
|
+
"""Detect the host terminal and active CLI agent from environment variables.
|
|
64
|
+
|
|
65
|
+
Warp sets ``TERM_PROGRAM=WarpTerminal`` (and ``TERM_PROGRAM_VERSION``).
|
|
66
|
+
As a fallback we also treat the presence of any ``WARP_*`` variable as a
|
|
67
|
+
Warp signal. Pass *env* to override ``os.environ`` (used by tests).
|
|
68
|
+
"""
|
|
69
|
+
source = os.environ if env is None else env
|
|
70
|
+
program = (source.get("TERM_PROGRAM") or "").strip()
|
|
71
|
+
version = (source.get("TERM_PROGRAM_VERSION") or "").strip()
|
|
72
|
+
is_warp = program == "WarpTerminal" or any(k.startswith("WARP_") for k in source)
|
|
73
|
+
if is_warp and not program:
|
|
74
|
+
program = "WarpTerminal"
|
|
75
|
+
|
|
76
|
+
# Detect the active CLI-agent REPL by checking known signal env vars.
|
|
77
|
+
# First match wins; order matters (specsmith checked before generic agents).
|
|
78
|
+
active_agent = ""
|
|
79
|
+
for agent, signals in _AGENT_ENV_SIGNALS.items():
|
|
80
|
+
if any(source.get(sig) for sig in signals):
|
|
81
|
+
active_agent = agent
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
return TerminalInfo(
|
|
85
|
+
is_warp=is_warp,
|
|
86
|
+
program=program,
|
|
87
|
+
version=version,
|
|
88
|
+
active_agent=active_agent,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# ---------------------------------------------------------------------------
|
|
93
|
+
# OSC 9 terminal notification (Warp, iTerm2, Windows Terminal)
|
|
94
|
+
# ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def emit_warp_notification(message: str, *, stream: TextIO | None = None) -> None:
|
|
98
|
+
"""Emit an OSC 9 terminal notification that Warp (and compatible terminals)
|
|
99
|
+
surfaces as a desktop notification.
|
|
100
|
+
|
|
101
|
+
The escape sequence ``ESC ] 9 ; <message> BEL`` is the standard notification
|
|
102
|
+
protocol supported by Warp, iTerm2, and Windows Terminal. When *stream* is
|
|
103
|
+
``None`` (the default), the function skips silently if stdout is not a TTY
|
|
104
|
+
(e.g. captured in tests or CI). Pass an explicit *stream* to override.
|
|
105
|
+
|
|
106
|
+
This is always safe to call — it is a no-op outside Warp and raises no
|
|
107
|
+
exceptions.
|
|
108
|
+
"""
|
|
109
|
+
out = stream if stream is not None else sys.stdout
|
|
110
|
+
try:
|
|
111
|
+
# When using the default stdout and it's not a tty, skip silently
|
|
112
|
+
# to avoid polluting captured output in tests or piped commands.
|
|
113
|
+
if stream is None and hasattr(out, "isatty") and not out.isatty():
|
|
114
|
+
return
|
|
115
|
+
out.write(f"\033]9;{message}\007")
|
|
116
|
+
if hasattr(out, "flush"):
|
|
117
|
+
out.flush()
|
|
118
|
+
except Exception: # noqa: BLE001 # intentional: notification is best-effort
|
|
119
|
+
pass
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
+
"""Warp integration adapter (REQ-444).
|
|
4
|
+
|
|
5
|
+
Generates Warp-native artifacts so Warp's agent is governed by specsmith:
|
|
6
|
+
|
|
7
|
+
* ``.warp/specsmith-mcp.json`` — governance MCP server config
|
|
8
|
+
* ``.warp/launch_configs/specsmith-governed.yaml`` — launch config for a governed session
|
|
9
|
+
* ``.agents/skills/SKILL.md`` — governance skill (shared with agent-skill)
|
|
10
|
+
|
|
11
|
+
``AGENTS.md`` is already the governance hub Warp reads as project Rules, so the
|
|
12
|
+
adapter does not duplicate it.
|
|
13
|
+
|
|
14
|
+
This adapter supersedes the pre-0.5.0 ``warp`` name that previously aliased to
|
|
15
|
+
the generic ``agent-skill`` adapter; the skill is still emitted here (by reusing
|
|
16
|
+
``AgentSkillAdapter``), so existing setups keep their ``.agents/skills/SKILL.md``.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
from specsmith.config import ProjectConfig
|
|
25
|
+
from specsmith.integrations.agent_skill import AgentSkillAdapter
|
|
26
|
+
from specsmith.integrations.base import AgentAdapter
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class WarpAdapter(AgentAdapter):
|
|
30
|
+
"""Generate Warp-native governance integration files."""
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def name(self) -> str:
|
|
34
|
+
return "warp"
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def description(self) -> str:
|
|
38
|
+
return "Warp native integration (MCP server config, launch config, governance skill)"
|
|
39
|
+
|
|
40
|
+
def generate(self, config: ProjectConfig, target: Path) -> list[Path]:
|
|
41
|
+
created: list[Path] = []
|
|
42
|
+
warp_dir = target / ".warp"
|
|
43
|
+
warp_dir.mkdir(parents=True, exist_ok=True)
|
|
44
|
+
|
|
45
|
+
# 1. MCP governance server config (shared builder with `mcp install-warp`).
|
|
46
|
+
from specsmith.mcp_server import build_warp_mcp_config
|
|
47
|
+
|
|
48
|
+
mcp_path = warp_dir / "specsmith-mcp.json"
|
|
49
|
+
mcp_path.write_text(
|
|
50
|
+
json.dumps(build_warp_mcp_config(), indent=2) + "\n",
|
|
51
|
+
encoding="utf-8",
|
|
52
|
+
)
|
|
53
|
+
created.append(mcp_path)
|
|
54
|
+
|
|
55
|
+
# 2. Launch config for a governed `specsmith run` session.
|
|
56
|
+
launch_dir = warp_dir / "launch_configs"
|
|
57
|
+
launch_dir.mkdir(parents=True, exist_ok=True)
|
|
58
|
+
launch_path = launch_dir / "specsmith-governed.yaml"
|
|
59
|
+
launch_path.write_text(self._render_launch_config(config, target), encoding="utf-8")
|
|
60
|
+
created.append(launch_path)
|
|
61
|
+
|
|
62
|
+
# 3. Governance skill (reuse the agent-skill adapter; .agents/skills/SKILL.md).
|
|
63
|
+
created.extend(AgentSkillAdapter().generate(config, target))
|
|
64
|
+
|
|
65
|
+
# 4. Third-party CLI agent toolbar setup guide.
|
|
66
|
+
setup_path = warp_dir / "SETUP.md"
|
|
67
|
+
setup_path.write_text(self._render_setup_guide(config), encoding="utf-8")
|
|
68
|
+
created.append(setup_path)
|
|
69
|
+
|
|
70
|
+
# Print the single most-important instruction so it appears immediately
|
|
71
|
+
# after `specsmith integrate warp` completes.
|
|
72
|
+
import sys
|
|
73
|
+
|
|
74
|
+
print(
|
|
75
|
+
"\n ↳ Warp toolbar (one-time, per machine):\n"
|
|
76
|
+
" Settings → Agents → Third party CLI agents\n"
|
|
77
|
+
" Commands that enable the toolbar → add regex:\n"
|
|
78
|
+
" specsmith\\s+run|aider\n"
|
|
79
|
+
" (claude, codex, gemini, cursor — already natively supported)\n"
|
|
80
|
+
"\n"
|
|
81
|
+
" Full setup guide: .warp/SETUP.md",
|
|
82
|
+
file=sys.stdout,
|
|
83
|
+
flush=True,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return created
|
|
87
|
+
|
|
88
|
+
def _render_setup_guide(self, config: ProjectConfig) -> str: # noqa: ARG002
|
|
89
|
+
"""Render the .warp/SETUP.md toolbar + notification setup guide."""
|
|
90
|
+
return """\
|
|
91
|
+
# Warp — specsmith governance integration
|
|
92
|
+
|
|
93
|
+
## Third-party CLI agent toolbar (one-time setup per machine)
|
|
94
|
+
|
|
95
|
+
Warp natively supports the toolbar for: **claude**, **codex**, **gemini**, **cursor**.
|
|
96
|
+
For **specsmith** and **aider** (not yet natively supported), add the following
|
|
97
|
+
regex to Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
specsmith\\s+run|aider
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Once saved, the Warp toolbelt appears automatically when either `specsmith run` or
|
|
104
|
+
`aider` is active in any pane, providing Rich Input (Ctrl+G), attach code as context,
|
|
105
|
+
File Explorer, Tab Configs, and Remote Control.
|
|
106
|
+
|
|
107
|
+
## Desktop notifications
|
|
108
|
+
|
|
109
|
+
`specsmith run` emits OSC 9 desktop notifications when running inside Warp
|
|
110
|
+
(or any OSC-9-compatible terminal such as iTerm2 or Windows Terminal).
|
|
111
|
+
No extra setup is needed — Warp intercepts the escape sequence automatically.
|
|
112
|
+
|
|
113
|
+
Notification events:
|
|
114
|
+
- Session start: `specsmith run | <project> | governance active`
|
|
115
|
+
|
|
116
|
+
## MCP governance server
|
|
117
|
+
|
|
118
|
+
Add `.warp/specsmith-mcp.json` to Warp → Settings → Agents → MCP servers so
|
|
119
|
+
Warp's Oz agent can call governance tools natively (preflight, audit, checkpoint,
|
|
120
|
+
req_list, phase, trace_seal) without shell roundtrips.
|
|
121
|
+
|
|
122
|
+
Paste the contents of `.warp/specsmith-mcp.json` or run:
|
|
123
|
+
```bash
|
|
124
|
+
specsmith mcp install-warp
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Launch configuration
|
|
128
|
+
|
|
129
|
+
`.warp/launch_configs/specsmith-governed.yaml` opens a governed `specsmith run`
|
|
130
|
+
session. Copy it to your Warp launch configurations directory:
|
|
131
|
+
- macOS/Linux: `~/.warp/launch_configurations/`
|
|
132
|
+
- Windows: `%APPDATA%/warp/Warp/data/launch_configurations/`
|
|
133
|
+
|
|
134
|
+
## Supported REPLs and their Warp status
|
|
135
|
+
|
|
136
|
+
| REPL | Toolbar | How |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| `specsmith run` | Custom regex | Add `specsmith\\s+run` to toolbar regex |
|
|
139
|
+
| `aider` | Custom regex | Add `aider` to toolbar regex |
|
|
140
|
+
| `claude` | Native | Built into Warp — no setup needed |
|
|
141
|
+
| `codex` | Native | Built into Warp — no setup needed |
|
|
142
|
+
| `gemini` | Native | Built into Warp — no setup needed |
|
|
143
|
+
| `cursor` | Native | Built into Warp — no setup needed |
|
|
144
|
+
|
|
145
|
+
## Session protocol (all REPLs)
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Session start
|
|
149
|
+
specsmith kill-session 2>/dev/null || true
|
|
150
|
+
specsmith audit --project-dir .
|
|
151
|
+
specsmith sync --project-dir .
|
|
152
|
+
specsmith checkpoint --project-dir . # output GOVERNANCE ANCHOR verbatim
|
|
153
|
+
|
|
154
|
+
# Before every code change
|
|
155
|
+
specsmith preflight "<describe the change>" --json
|
|
156
|
+
|
|
157
|
+
# Session end
|
|
158
|
+
specsmith save && specsmith kill-session
|
|
159
|
+
```
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
def _render_launch_config(self, config: ProjectConfig, target: Path) -> str:
|
|
163
|
+
cwd = str(target).replace("\\", "/")
|
|
164
|
+
return f"""\
|
|
165
|
+
# specsmith governed session — Warp launch configuration.
|
|
166
|
+
# Copy to your Warp launch configurations directory to use it:
|
|
167
|
+
# macOS/Linux: ~/.warp/launch_configurations/
|
|
168
|
+
# Windows: %APPDATA%/warp/Warp/data/launch_configurations/
|
|
169
|
+
# The governance MCP server config lives in .warp/specsmith-mcp.json — add it
|
|
170
|
+
# under Warp Settings -> Agents -> MCP servers so Warp's agent is governed.
|
|
171
|
+
name: {config.name} — specsmith governed
|
|
172
|
+
windows:
|
|
173
|
+
- tabs:
|
|
174
|
+
- title: specsmith
|
|
175
|
+
layout:
|
|
176
|
+
cwd: "{cwd}"
|
|
177
|
+
commands:
|
|
178
|
+
- exec: specsmith run
|
|
179
|
+
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specsmith
|
|
3
|
-
Version: 0.20.1.
|
|
3
|
+
Version: 0.20.1.dev759
|
|
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
|
|
@@ -1341,6 +1341,20 @@ oz agent run --mcp '{"specsmith-governance": {"command": "specsmith", "args": ["
|
|
|
1341
1341
|
| `governance_req_list` | All requirements with status + test coverage, filterable |
|
|
1342
1342
|
| `governance_trace_seal` | Create a cryptographic trace vault seal |
|
|
1343
1343
|
|
|
1344
|
+
### Third-party CLI agent toolbar
|
|
1345
|
+
|
|
1346
|
+
For **specsmith** and **aider** (not yet natively supported by Warp), add this regex once in **Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar**:
|
|
1347
|
+
|
|
1348
|
+
```
|
|
1349
|
+
specsmith\s+run|aider
|
|
1350
|
+
```
|
|
1351
|
+
|
|
1352
|
+
`claude`, `codex`, `gemini`, and `cursor` are already natively supported — no regex needed.
|
|
1353
|
+
|
|
1354
|
+
Once set, the toolbelt (Rich Input, attach code, File Explorer, Tab Configs, Remote Control) appears whenever `specsmith run` or `aider` is running. `specsmith run` also emits an OSC 9 desktop notification on session start — intercepted automatically by Warp, iTerm2, and Windows Terminal.
|
|
1355
|
+
|
|
1356
|
+
Run `specsmith integrate warp` to regenerate `.warp/SETUP.md` with the full per-REPL setup guide.
|
|
1357
|
+
|
|
1344
1358
|
### Repository Workflows (Ctrl+Shift+R)
|
|
1345
1359
|
|
|
1346
1360
|
Clone this repo and open it in Warp — seven governance workflows appear automatically in
|
|
@@ -79,6 +79,30 @@ class TestWarpAdapterGenerate:
|
|
|
79
79
|
assert "test-project" in content
|
|
80
80
|
assert "AGENTS.md" in content
|
|
81
81
|
|
|
82
|
+
def test_generates_setup_md(self, config: ProjectConfig, tmp_path: Path) -> None:
|
|
83
|
+
WarpAdapter().generate(config, tmp_path)
|
|
84
|
+
setup = tmp_path / ".warp" / "SETUP.md"
|
|
85
|
+
assert setup.exists()
|
|
86
|
+
content = setup.read_text(encoding="utf-8")
|
|
87
|
+
# Must document the toolbar regex for non-native REPLs.
|
|
88
|
+
assert "specsmith" in content
|
|
89
|
+
assert "aider" in content
|
|
90
|
+
# Must distinguish natively supported agents.
|
|
91
|
+
assert "claude" in content
|
|
92
|
+
assert "Native" in content
|
|
93
|
+
|
|
94
|
+
def test_setup_md_contains_toolbar_regex(self, config: ProjectConfig, tmp_path: Path) -> None:
|
|
95
|
+
WarpAdapter().generate(config, tmp_path)
|
|
96
|
+
setup = tmp_path / ".warp" / "SETUP.md"
|
|
97
|
+
content = setup.read_text(encoding="utf-8")
|
|
98
|
+
# The regex the user must paste into Warp settings.
|
|
99
|
+
assert r"specsmith\s+run|aider" in content
|
|
100
|
+
|
|
101
|
+
def test_generated_files_includes_setup_md(self, config: ProjectConfig, tmp_path: Path) -> None:
|
|
102
|
+
files = WarpAdapter().generate(config, tmp_path)
|
|
103
|
+
rel = {p.relative_to(tmp_path).as_posix() for p in files}
|
|
104
|
+
assert ".warp/SETUP.md" in rel
|
|
105
|
+
|
|
82
106
|
def test_idempotent(self, config: ProjectConfig, tmp_path: Path) -> None:
|
|
83
107
|
first = WarpAdapter().generate(config, tmp_path)
|
|
84
108
|
first_contents = {p: p.read_text(encoding="utf-8") for p in first}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
+
"""Tests for host-terminal detection (REQ-444)."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import io
|
|
8
|
+
|
|
9
|
+
from specsmith.agent.terminal_env import TerminalInfo, detect_terminal, emit_warp_notification
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestDetectTerminal:
|
|
13
|
+
def test_detects_warp_via_term_program(self) -> None:
|
|
14
|
+
info = detect_terminal(
|
|
15
|
+
{"TERM_PROGRAM": "WarpTerminal", "TERM_PROGRAM_VERSION": "0.2026.06.01"}
|
|
16
|
+
)
|
|
17
|
+
assert info.is_warp is True
|
|
18
|
+
assert info.program == "WarpTerminal"
|
|
19
|
+
assert info.version == "0.2026.06.01"
|
|
20
|
+
|
|
21
|
+
def test_detects_warp_via_warp_env_var(self) -> None:
|
|
22
|
+
info = detect_terminal({"WARP_HONOR_PS1": "0"})
|
|
23
|
+
assert info.is_warp is True
|
|
24
|
+
# Program is backfilled when only a WARP_* signal is present.
|
|
25
|
+
assert info.program == "WarpTerminal"
|
|
26
|
+
|
|
27
|
+
def test_non_warp_terminal(self) -> None:
|
|
28
|
+
info = detect_terminal({"TERM_PROGRAM": "iTerm.app"})
|
|
29
|
+
assert info.is_warp is False
|
|
30
|
+
assert info.program == "iTerm.app"
|
|
31
|
+
assert info.version == ""
|
|
32
|
+
|
|
33
|
+
def test_empty_env(self) -> None:
|
|
34
|
+
info = detect_terminal({})
|
|
35
|
+
assert info.is_warp is False
|
|
36
|
+
assert info.program == ""
|
|
37
|
+
assert info.version == ""
|
|
38
|
+
|
|
39
|
+
def test_as_dict_round_trip(self) -> None:
|
|
40
|
+
info = detect_terminal({"TERM_PROGRAM": "WarpTerminal"})
|
|
41
|
+
d = info.as_dict()
|
|
42
|
+
assert d == {
|
|
43
|
+
"is_warp": True,
|
|
44
|
+
"program": "WarpTerminal",
|
|
45
|
+
"version": "",
|
|
46
|
+
"active_agent": "",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
def test_frozen_dataclass(self) -> None:
|
|
50
|
+
info = TerminalInfo(is_warp=False, program="x", version="1")
|
|
51
|
+
try:
|
|
52
|
+
info.is_warp = True # type: ignore[misc]
|
|
53
|
+
except AttributeError:
|
|
54
|
+
pass
|
|
55
|
+
else: # pragma: no cover - dataclass should be frozen
|
|
56
|
+
raise AssertionError("TerminalInfo should be frozen")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class TestActiveAgentDetection:
|
|
60
|
+
def test_detects_specsmith_repl(self) -> None:
|
|
61
|
+
info = detect_terminal({"SPECSMITH_RUN_ACTIVE": "1"})
|
|
62
|
+
assert info.active_agent == "specsmith"
|
|
63
|
+
|
|
64
|
+
def test_detects_aider_via_model(self) -> None:
|
|
65
|
+
info = detect_terminal({"AIDER_MODEL": "gpt-4o"})
|
|
66
|
+
assert info.active_agent == "aider"
|
|
67
|
+
|
|
68
|
+
def test_detects_aider_via_config(self) -> None:
|
|
69
|
+
info = detect_terminal({"AIDER_CONFIG": "/home/user/.aider.conf.yml"})
|
|
70
|
+
assert info.active_agent == "aider"
|
|
71
|
+
|
|
72
|
+
def test_detects_claude(self) -> None:
|
|
73
|
+
info = detect_terminal({"CLAUDE_CODE_ENTRYPOINT": "cli"})
|
|
74
|
+
assert info.active_agent == "claude"
|
|
75
|
+
|
|
76
|
+
def test_detects_codex(self) -> None:
|
|
77
|
+
info = detect_terminal({"CODEX_CLI_SESSION": "abc123"})
|
|
78
|
+
assert info.active_agent == "codex"
|
|
79
|
+
|
|
80
|
+
def test_detects_gemini(self) -> None:
|
|
81
|
+
info = detect_terminal({"GEMINI_CLI": "1"})
|
|
82
|
+
assert info.active_agent == "gemini"
|
|
83
|
+
|
|
84
|
+
def test_no_agent_in_plain_shell(self) -> None:
|
|
85
|
+
info = detect_terminal({"TERM_PROGRAM": "iTerm.app"})
|
|
86
|
+
assert info.active_agent == ""
|
|
87
|
+
|
|
88
|
+
def test_specsmith_wins_over_aider_when_both_present(self) -> None:
|
|
89
|
+
# SPECSMITH_RUN_ACTIVE is checked first in the signals dict.
|
|
90
|
+
info = detect_terminal({"SPECSMITH_RUN_ACTIVE": "1", "AIDER_MODEL": "gpt-4o"})
|
|
91
|
+
assert info.active_agent == "specsmith"
|
|
92
|
+
|
|
93
|
+
def test_active_agent_included_in_as_dict(self) -> None:
|
|
94
|
+
info = detect_terminal({"AIDER_MODEL": "claude-3-5-sonnet"})
|
|
95
|
+
assert info.as_dict()["active_agent"] == "aider"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class TestEmitWarpNotification:
|
|
99
|
+
def test_writes_osc9_sequence_to_explicit_stream(self) -> None:
|
|
100
|
+
buf = io.StringIO()
|
|
101
|
+
emit_warp_notification("hello warp", stream=buf)
|
|
102
|
+
assert buf.getvalue() == "\033]9;hello warp\007"
|
|
103
|
+
|
|
104
|
+
def test_message_is_included_verbatim(self) -> None:
|
|
105
|
+
buf = io.StringIO()
|
|
106
|
+
emit_warp_notification("specsmith run | myproj | governance active", stream=buf)
|
|
107
|
+
assert "specsmith run | myproj | governance active" in buf.getvalue()
|
|
108
|
+
|
|
109
|
+
def test_empty_message_still_writes_osc_frame(self) -> None:
|
|
110
|
+
buf = io.StringIO()
|
|
111
|
+
emit_warp_notification("", stream=buf)
|
|
112
|
+
# Should still write the OSC frame (empty body is valid)
|
|
113
|
+
assert "\033]9;" in buf.getvalue()
|
|
114
|
+
|
|
115
|
+
def test_no_exception_on_closed_stream(self) -> None:
|
|
116
|
+
buf = io.StringIO()
|
|
117
|
+
buf.close()
|
|
118
|
+
# Must not raise
|
|
119
|
+
emit_warp_notification("test", stream=buf)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class TestBannerReflectsTerminal:
|
|
123
|
+
def test_runner_reads_terminal(self, tmp_path, monkeypatch) -> None:
|
|
124
|
+
monkeypatch.setenv("TERM_PROGRAM", "WarpTerminal")
|
|
125
|
+
from specsmith.agent.runner import AgentRunner
|
|
126
|
+
|
|
127
|
+
runner = AgentRunner(project_dir=str(tmp_path), json_events=True)
|
|
128
|
+
assert runner.terminal.is_warp is True
|
|
129
|
+
|
|
130
|
+
def test_runner_sets_specsmith_run_active(self, tmp_path, monkeypatch) -> None:
|
|
131
|
+
import os
|
|
132
|
+
|
|
133
|
+
monkeypatch.delenv("SPECSMITH_RUN_ACTIVE", raising=False)
|
|
134
|
+
from specsmith.agent.runner import AgentRunner
|
|
135
|
+
|
|
136
|
+
AgentRunner(project_dir=str(tmp_path), json_events=True)
|
|
137
|
+
assert os.environ.get("SPECSMITH_RUN_ACTIVE") == "1"
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# SPDX-License-Identifier: MIT
|
|
2
|
-
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
-
"""Terminal-environment detection for specsmith (REQ-444).
|
|
4
|
-
|
|
5
|
-
Lets the interactive REPL (``specsmith run``) detect when it is running
|
|
6
|
-
inside Warp so it can adapt its banner / ``ready`` frame. Detection is
|
|
7
|
-
based on the standard ``TERM_PROGRAM`` signal Warp sets, plus any
|
|
8
|
-
``WARP_*`` environment variables, and is purely read-only.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from __future__ import annotations
|
|
12
|
-
|
|
13
|
-
import os
|
|
14
|
-
from dataclasses import asdict, dataclass
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@dataclass(frozen=True)
|
|
18
|
-
class TerminalInfo:
|
|
19
|
-
"""Information about the host terminal."""
|
|
20
|
-
|
|
21
|
-
is_warp: bool
|
|
22
|
-
program: str
|
|
23
|
-
version: str
|
|
24
|
-
|
|
25
|
-
def as_dict(self) -> dict[str, object]:
|
|
26
|
-
"""Return a flat dict suitable for the ``ready`` event frame."""
|
|
27
|
-
return asdict(self)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def detect_terminal(env: dict[str, str] | None = None) -> TerminalInfo:
|
|
31
|
-
"""Detect the host terminal from environment variables.
|
|
32
|
-
|
|
33
|
-
Warp sets ``TERM_PROGRAM=WarpTerminal`` (and ``TERM_PROGRAM_VERSION``).
|
|
34
|
-
As a fallback we also treat the presence of any ``WARP_*`` variable as a
|
|
35
|
-
Warp signal. Pass *env* to override ``os.environ`` (used by tests).
|
|
36
|
-
"""
|
|
37
|
-
source = os.environ if env is None else env
|
|
38
|
-
program = (source.get("TERM_PROGRAM") or "").strip()
|
|
39
|
-
version = (source.get("TERM_PROGRAM_VERSION") or "").strip()
|
|
40
|
-
is_warp = program == "WarpTerminal" or any(k.startswith("WARP_") for k in source)
|
|
41
|
-
if is_warp and not program:
|
|
42
|
-
program = "WarpTerminal"
|
|
43
|
-
return TerminalInfo(is_warp=is_warp, program=program, version=version)
|