specsmith 0.11.3.dev433__tar.gz → 0.11.3.dev436__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.11.3.dev433/src/specsmith.egg-info → specsmith-0.11.3.dev436}/PKG-INFO +1 -1
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/pyproject.toml +1 -1
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/cli.py +172 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/config.py +77 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/migrations/__init__.py +2 -0
- specsmith-0.11.3.dev436/src/specsmith/migrations/m006_session_governance.py +230 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/phase.py +147 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/devops.py +186 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/governance.py +243 -0
- specsmith-0.11.3.dev436/src/specsmith/templates/agents.md.j2 +109 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/tools.py +49 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436/src/specsmith.egg-info}/PKG-INFO +1 -1
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith.egg-info/SOURCES.txt +1 -0
- specsmith-0.11.3.dev433/src/specsmith/templates/agents.md.j2 +0 -61
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/LICENSE +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/README.md +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/setup.cfg +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/belief.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/certainty.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/failure_graph.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/py.typed +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/recovery.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/session.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/stress_tester.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/epistemic/trace.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/__main__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/broker.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/chat_runner.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/cleanup.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/context_seed.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/core.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/dispatch/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/dispatch/_status.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/dispatch/dag.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/dispatch/events.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/dispatch/result.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/endpoints.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/events.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/execution_profiles.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/fallback.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/hf_leaderboard.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/hf_sync.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/indexer.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/llm_client.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/mcp.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/memory.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/model_intelligence.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/model_profiles.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/orchestrator.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/permissions.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/profiles.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/provider_registry.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/repl.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/router.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/rules.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/runner.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/safety.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/spawner.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/suggester.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/teams.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/tools.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/verifier.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/agent/voice.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/architect.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/auditor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/auth.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/block_export.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/channel.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/ci_manager.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/commands/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/commands/intelligence.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/compliance/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/compliance/_compat.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/compliance/checker.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/compliance/evidence.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/compliance/regulations.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/compliance/reporter.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/compressor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/console_utils.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/context_orchestrator.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/context_window.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/credit_analyzer.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/credits.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/base.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/citations.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/fpd.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/odp.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/patentsview.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/pfw.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/ppubs.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/datasources/ptab.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/differ.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/doctor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/drive.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/editor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/epistemic/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/epistemic/belief.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/epistemic/certainty.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/epistemic/failure_graph.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/epistemic/recovery.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/epistemic/stress_tester.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/esdb/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/esdb/bridge.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/eval/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/eval/builtins.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/eval/runner.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/executor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/exporter.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/governance_logic.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/governance_store.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/governance_yaml.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/app.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/main_window.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/session_tab.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/theme.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/widgets/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/widgets/chat_view.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/widgets/input_bar.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/widgets/provider_bar.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/widgets/token_meter.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/widgets/tool_panel.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/widgets/update_checker.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/gui/worker.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/history_search.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/importer.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/instinct.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/agent_skill.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/aider.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/base.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/claude_code.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/copilot.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/cursor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/gemini.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/integrations/windsurf.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/issue_reporter.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/languages.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/ledger.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/mcp_generator.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/migrations/m002_agents_slim.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/migrations/m003_compliance_init.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/migrations/runner.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/ollama_cmds.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/patent.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/paths.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/plugins.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/profiles.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/rate_limits.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/releaser.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/requirements.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/requirements_parser.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/retrieval.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/safe_write.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/scaffolder.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/serve.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/session.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/session_init.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/session_store.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/cloud.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/corporate.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/cross_platform.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/docs.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/embedded.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/hardware.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/mobile.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/productivity.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills/ssh.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/skills_builder.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/sync.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/contributing.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/license-MIT.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/community/security.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/editorconfig.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/gitattributes.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/gitignore.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/go/go.mod.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/go/main.go.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/roles.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/rules.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/governance/verification.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/js/package.json.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/ledger.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/python/cli.py.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/python/init.py.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/readme.md.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/rust/main.rs.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/tool_installer.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/toolrules.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/trace.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/updater.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/upgrader.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/validator.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/vcs/__init__.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/vcs/base.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/vcs/bitbucket.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/vcs/github.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/vcs/gitlab.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/vcs_commands.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/wireframes.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith/workspace.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith.egg-info/dependency_links.txt +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith.egg-info/entry_points.txt +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith.egg-info/requires.txt +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/src/specsmith.egg-info/top_level.txt +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_CMD_001.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_agent_profiles.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_agent_runner_ready.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_ai_client.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_ai_intelligence.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_auditor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_channel.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_chat_diff_decision.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_chat_runner_openai_compat.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_chat_stdin_protocol.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_cli.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_cli_workflows_history_drive.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_compliance.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_compressor.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_dispatch.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_e2e_nexus.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_endpoints_cli.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_endpoints_store.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_epistemic.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_fallback_chain.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_importer.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_integrations.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_intelligence.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_issue_reporter.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_mcp_client.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_new_modules.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_nexus.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_permissions.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_phase1_4_new.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_phase34_completion.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_rate_limits.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_req_248_262.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_scaffolder.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_skill_marketplace.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_skills_mcp.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_smoke.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_suggester.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_tools.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_validator.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_vcs.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_warp_parity.py +0 -0
- {specsmith-0.11.3.dev433 → specsmith-0.11.3.dev436}/tests/test_warp_parity_followup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specsmith
|
|
3
|
-
Version: 0.11.3.
|
|
3
|
+
Version: 0.11.3.dev436
|
|
4
4
|
Summary: Applied Epistemic Engineering toolkit — AEE agent sessions, execution profiles, FPGA/HDL governance, tool installer, 50+ CLI commands.
|
|
5
5
|
Author: BitConcepts
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specsmith"
|
|
7
|
-
version = "0.11.3.
|
|
7
|
+
version = "0.11.3.dev436"
|
|
8
8
|
description = "Applied Epistemic Engineering toolkit — AEE agent sessions, execution profiles, FPGA/HDL governance, tool installer, 50+ CLI commands."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -2999,6 +2999,178 @@ def session_clear_cmd(project_dir: str, yes: bool) -> None:
|
|
|
2999
2999
|
console.print("[green]\u2713[/green] Session context cleared.")
|
|
3000
3000
|
|
|
3001
3001
|
|
|
3002
|
+
@main.command(name="checkpoint")
|
|
3003
|
+
@click.option("--project-dir", type=click.Path(exists=True), default=".")
|
|
3004
|
+
@click.option("--json", "as_json", is_flag=True, default=False, help="Emit as JSON.")
|
|
3005
|
+
def checkpoint_cmd(project_dir: str, as_json: bool) -> None:
|
|
3006
|
+
"""Emit a compact governance anchor to prevent session drift.
|
|
3007
|
+
|
|
3008
|
+
Run this every 8-10 turns and ALWAYS include the output in any context
|
|
3009
|
+
summary. The anchor captures the exact governance state (phase, health,
|
|
3010
|
+
work items, REQ/TEST counts, ESDB chain) so the next context window is
|
|
3011
|
+
never blind to where the project stands.
|
|
3012
|
+
|
|
3013
|
+
Usage pattern (copy the output into the conversation)::
|
|
3014
|
+
|
|
3015
|
+
specsmith checkpoint # human-readable anchor block
|
|
3016
|
+
specsmith checkpoint --json # machine-readable JSON
|
|
3017
|
+
|
|
3018
|
+
In AGENTS.md: agents MUST emit ``specsmith checkpoint`` output verbatim
|
|
3019
|
+
whenever they produce a context summary.
|
|
3020
|
+
"""
|
|
3021
|
+
import json as _json
|
|
3022
|
+
import re
|
|
3023
|
+
import time
|
|
3024
|
+
|
|
3025
|
+
root = Path(project_dir).resolve()
|
|
3026
|
+
ts = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
3027
|
+
|
|
3028
|
+
# ── Project name ──────────────────────────────────────────────────────────
|
|
3029
|
+
project_name = root.name
|
|
3030
|
+
try:
|
|
3031
|
+
from specsmith.paths import find_scaffold
|
|
3032
|
+
|
|
3033
|
+
sp = find_scaffold(root)
|
|
3034
|
+
if sp:
|
|
3035
|
+
import yaml as _yaml
|
|
3036
|
+
|
|
3037
|
+
raw = _yaml.safe_load(sp.read_text(encoding="utf-8")) or {}
|
|
3038
|
+
project_name = str(raw.get("name", root.name))
|
|
3039
|
+
except Exception: # noqa: BLE001
|
|
3040
|
+
pass
|
|
3041
|
+
|
|
3042
|
+
# ── Phase ─────────────────────────────────────────────────────────────────
|
|
3043
|
+
phase_key, phase_label, phase_emoji, phase_pct = "unknown", "Unknown", "", 0
|
|
3044
|
+
try:
|
|
3045
|
+
from specsmith.phase import PHASE_MAP, phase_progress_pct, read_phase
|
|
3046
|
+
|
|
3047
|
+
phase_key = read_phase(root)
|
|
3048
|
+
phase = PHASE_MAP.get(phase_key)
|
|
3049
|
+
if phase:
|
|
3050
|
+
phase_label = phase.label
|
|
3051
|
+
phase_emoji = phase.emoji
|
|
3052
|
+
phase_pct = phase_progress_pct(phase, root)
|
|
3053
|
+
except Exception: # noqa: BLE001
|
|
3054
|
+
pass
|
|
3055
|
+
|
|
3056
|
+
# ── Audit health ──────────────────────────────────────────────────────────
|
|
3057
|
+
health_ok, audit_failed = True, 0
|
|
3058
|
+
try:
|
|
3059
|
+
from specsmith.auditor import run_audit
|
|
3060
|
+
|
|
3061
|
+
report = run_audit(root)
|
|
3062
|
+
health_ok = report.healthy
|
|
3063
|
+
audit_failed = report.failed
|
|
3064
|
+
except Exception: # noqa: BLE001
|
|
3065
|
+
pass
|
|
3066
|
+
|
|
3067
|
+
# ── REQ / TEST counts ─────────────────────────────────────────────────────
|
|
3068
|
+
req_count, test_count = 0, 0
|
|
3069
|
+
try:
|
|
3070
|
+
import json as _jl
|
|
3071
|
+
|
|
3072
|
+
rp = root / ".specsmith" / "requirements.json"
|
|
3073
|
+
tp = root / ".specsmith" / "testcases.json"
|
|
3074
|
+
if rp.exists():
|
|
3075
|
+
req_count = len(_jl.loads(rp.read_text(encoding="utf-8")))
|
|
3076
|
+
if tp.exists():
|
|
3077
|
+
test_count = len(_jl.loads(tp.read_text(encoding="utf-8")))
|
|
3078
|
+
except Exception: # noqa: BLE001
|
|
3079
|
+
pass
|
|
3080
|
+
|
|
3081
|
+
# ── ESDB ──────────────────────────────────────────────────────────────────
|
|
3082
|
+
esdb_ok, esdb_records = True, 0
|
|
3083
|
+
try:
|
|
3084
|
+
from chronomemory import ChronoStore
|
|
3085
|
+
|
|
3086
|
+
wal = root / ".chronomemory" / "events.wal"
|
|
3087
|
+
if wal.exists():
|
|
3088
|
+
with ChronoStore(root) as store:
|
|
3089
|
+
esdb_ok = store.chain_valid()
|
|
3090
|
+
esdb_records = store.record_count()
|
|
3091
|
+
except Exception: # noqa: BLE001
|
|
3092
|
+
pass
|
|
3093
|
+
|
|
3094
|
+
# ── Recent work items + last preflight from LEDGER.md ─────────────────────
|
|
3095
|
+
recent_wis: list[str] = []
|
|
3096
|
+
last_preflight = ""
|
|
3097
|
+
try:
|
|
3098
|
+
ledger_candidates = ["docs/LEDGER.md", "LEDGER.md"]
|
|
3099
|
+
for cand in ledger_candidates:
|
|
3100
|
+
lp = root / cand
|
|
3101
|
+
if lp.exists():
|
|
3102
|
+
text = lp.read_text(encoding="utf-8", errors="ignore")
|
|
3103
|
+
wis = re.findall(r"\bWI-[A-F0-9]{8}\b", text)
|
|
3104
|
+
seen: set[str] = set()
|
|
3105
|
+
for wi in reversed(wis):
|
|
3106
|
+
if wi not in seen:
|
|
3107
|
+
seen.add(wi)
|
|
3108
|
+
recent_wis.insert(0, wi)
|
|
3109
|
+
if len(seen) >= 3:
|
|
3110
|
+
break
|
|
3111
|
+
pf = re.findall(r"preflight accepted[^\n]{0,80}", text)
|
|
3112
|
+
if pf:
|
|
3113
|
+
last_preflight = pf[-1]
|
|
3114
|
+
break
|
|
3115
|
+
except Exception: # noqa: BLE001
|
|
3116
|
+
pass
|
|
3117
|
+
|
|
3118
|
+
payload: dict[str, Any] = {
|
|
3119
|
+
"ts": ts,
|
|
3120
|
+
"project": project_name,
|
|
3121
|
+
"phase": phase_key,
|
|
3122
|
+
"phase_label": f"{phase_emoji} {phase_label}",
|
|
3123
|
+
"phase_pct": phase_pct,
|
|
3124
|
+
"health": "clean" if health_ok else f"{audit_failed} issues",
|
|
3125
|
+
"audit_failed": audit_failed,
|
|
3126
|
+
"req_count": req_count,
|
|
3127
|
+
"test_count": test_count,
|
|
3128
|
+
"esdb_records": esdb_records,
|
|
3129
|
+
"esdb_chain_valid": esdb_ok,
|
|
3130
|
+
"recent_wis": recent_wis,
|
|
3131
|
+
"last_preflight": last_preflight,
|
|
3132
|
+
"anchor": f"SPECSMITH-ANCHOR-{ts}",
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
if as_json:
|
|
3136
|
+
click.echo(_json.dumps(payload, indent=2))
|
|
3137
|
+
return
|
|
3138
|
+
|
|
3139
|
+
# ── Human-readable anchor block ───────────────────────────────────────────
|
|
3140
|
+
# Designed to be compact and survive context summarization.
|
|
3141
|
+
hbar = "\u2550" * 57 # ═══…
|
|
3142
|
+
vbar = "\u2551" # ║
|
|
3143
|
+
health_icon = "\u2713" if health_ok else "\u2717"
|
|
3144
|
+
esdb_icon = "\u2713" if esdb_ok else "\u2717"
|
|
3145
|
+
wi_str = ", ".join(recent_wis) if recent_wis else "none seen"
|
|
3146
|
+
|
|
3147
|
+
console.print(f"[bold cyan]\u2554{hbar}\u2557[/bold cyan]")
|
|
3148
|
+
console.print(f"[bold cyan]{vbar}[/bold cyan] GOVERNANCE ANCHOR {ts}")
|
|
3149
|
+
console.print(f"[bold cyan]{vbar}[/bold cyan] Project : [bold]{project_name}[/bold]")
|
|
3150
|
+
console.print(
|
|
3151
|
+
f"[bold cyan]{vbar}[/bold cyan] Phase : {phase_emoji} {phase_label} ({phase_pct}%)"
|
|
3152
|
+
)
|
|
3153
|
+
health_str = (
|
|
3154
|
+
f"[green]{health_icon} clean[/green]"
|
|
3155
|
+
if health_ok
|
|
3156
|
+
else f"[red]{health_icon} {audit_failed} issues[/red]"
|
|
3157
|
+
)
|
|
3158
|
+
console.print(f"[bold cyan]{vbar}[/bold cyan] Health : {health_str}")
|
|
3159
|
+
console.print(
|
|
3160
|
+
f"[bold cyan]{vbar}[/bold cyan] REQs : {req_count} TESTs: {test_count}"
|
|
3161
|
+
f" ESDB: {esdb_records} records ({esdb_icon} chain)"
|
|
3162
|
+
)
|
|
3163
|
+
console.print(f"[bold cyan]{vbar}[/bold cyan] WIs : {wi_str}")
|
|
3164
|
+
if last_preflight:
|
|
3165
|
+
pf_short = last_preflight[:55]
|
|
3166
|
+
console.print(f"[bold cyan]{vbar}[/bold cyan] Preflight: {pf_short}")
|
|
3167
|
+
console.print(f"[bold cyan]\u255a{hbar}\u255d[/bold cyan]")
|
|
3168
|
+
console.print(
|
|
3169
|
+
"[dim]Include this block verbatim in any context summary "
|
|
3170
|
+
r"(\`specsmith checkpoint\` re-generates it).[/dim]"
|
|
3171
|
+
)
|
|
3172
|
+
|
|
3173
|
+
|
|
3002
3174
|
@main.command(name="session-end")
|
|
3003
3175
|
@click.option("--project-dir", type=click.Path(exists=True), default=".")
|
|
3004
3176
|
def session_end_cmd(project_dir: str) -> None:
|
|
@@ -66,6 +66,14 @@ class ProjectType(str, Enum):
|
|
|
66
66
|
EMBEDDED_PYTHON_HMI = "embedded-python-hmi" # #109: hardware-interfacing kiosk/HMI
|
|
67
67
|
RESEARCH_PYTHON = "research-python" # #153: experiment/research packages (no CLI)
|
|
68
68
|
SAFETY_CRITICAL = "safety-critical" # #129: IEC 60204-1/62061/61508 safety-critical
|
|
69
|
+
# IP / Patent
|
|
70
|
+
PATENT_PROSECUTION = "patent-prosecution" # #177: IP prosecution with USPTO MCP lifecycle
|
|
71
|
+
# Modern web frameworks
|
|
72
|
+
NEXTJS_APP = "nextjs-app" # Next.js / React full-stack app
|
|
73
|
+
NUXT_APP = "nuxt-app" # Nuxt.js / Vue full-stack app
|
|
74
|
+
SVELTEKIT_APP = "sveltekit-app" # SvelteKit app
|
|
75
|
+
REMIX_APP = "remix-app" # Remix full-stack React app
|
|
76
|
+
ASTRO_SITE = "astro-site" # Astro static/SSR site
|
|
69
77
|
|
|
70
78
|
|
|
71
79
|
class Platform(str, Enum):
|
|
@@ -194,6 +202,67 @@ class ProjectConfig(BaseModel):
|
|
|
194
202
|
),
|
|
195
203
|
)
|
|
196
204
|
|
|
205
|
+
# Fallback type — used when this project type is not yet supported
|
|
206
|
+
# by the installed specsmith version. specsmith silently falls back to
|
|
207
|
+
# this type for scaffolding purposes while still recording the intended type.
|
|
208
|
+
fallback_type: str = Field(
|
|
209
|
+
default="",
|
|
210
|
+
description=(
|
|
211
|
+
"Fallback project type for scaffold generation when `type` is not yet "
|
|
212
|
+
"supported by the installed specsmith version (e.g. 'spec-document' as "
|
|
213
|
+
"fallback for 'patent-prosecution')."
|
|
214
|
+
),
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# IP prosecution fields (used when type == 'patent-prosecution')
|
|
218
|
+
provisional_app_number: str = Field(
|
|
219
|
+
default="", description="USPTO provisional application number (e.g. '63/980,251')"
|
|
220
|
+
)
|
|
221
|
+
provisional_filed_date: str = Field(
|
|
222
|
+
default="", description="Date the provisional was filed (YYYY-MM-DD)"
|
|
223
|
+
)
|
|
224
|
+
non_provisional_deadline: str = Field(
|
|
225
|
+
default="",
|
|
226
|
+
description="12-month non-provisional conversion deadline (YYYY-MM-DD)",
|
|
227
|
+
)
|
|
228
|
+
entity_status: str = Field(default="", description="USPTO entity status: small, micro, large")
|
|
229
|
+
assignee: str = Field(default="", description="Patent assignee / rights holder")
|
|
230
|
+
counsel: str = Field(default="", description="Patent counsel firm name")
|
|
231
|
+
inventors: list[dict[str, str]] = Field(
|
|
232
|
+
default_factory=list,
|
|
233
|
+
description="List of inventors with name and role keys",
|
|
234
|
+
)
|
|
235
|
+
ip_families: list[dict[str, Any]] = Field(
|
|
236
|
+
default_factory=list,
|
|
237
|
+
description=(
|
|
238
|
+
"IP patent families. Each entry: {id, name, phase, provisional, themes, "
|
|
239
|
+
"anchor_spec, ...}."
|
|
240
|
+
),
|
|
241
|
+
)
|
|
242
|
+
claim_themes: list[dict[str, Any]] = Field(
|
|
243
|
+
default_factory=list,
|
|
244
|
+
description=(
|
|
245
|
+
"Claim themes for the primary IP family. Each entry: {id, name, description, "
|
|
246
|
+
"risk, primary_comparator, last_par_run}."
|
|
247
|
+
),
|
|
248
|
+
)
|
|
249
|
+
specs_dir: str = Field(
|
|
250
|
+
default="docs/ip/specs",
|
|
251
|
+
description="Normative specification directory for IP repos",
|
|
252
|
+
)
|
|
253
|
+
prosecution_dir: str = Field(
|
|
254
|
+
default="docs/ip/prosecution",
|
|
255
|
+
description="Prior-art protocol and prosecution planning directory",
|
|
256
|
+
)
|
|
257
|
+
strategy_dir: str = Field(
|
|
258
|
+
default="docs/ip/strategy",
|
|
259
|
+
description="IP strategy documents directory",
|
|
260
|
+
)
|
|
261
|
+
filings_dir: str = Field(
|
|
262
|
+
default="docs/ip/filings",
|
|
263
|
+
description="Immutable filed artifacts directory",
|
|
264
|
+
)
|
|
265
|
+
|
|
197
266
|
# FPGA-specific
|
|
198
267
|
fpga_vendor: str = Field(
|
|
199
268
|
default="",
|
|
@@ -471,6 +540,14 @@ _TYPE_LABELS: dict[str, str] = {
|
|
|
471
540
|
ProjectType.EMBEDDED_PYTHON_HMI: "Embedded Python HMI / kiosk (hardware-interfacing)",
|
|
472
541
|
ProjectType.RESEARCH_PYTHON: "Research Python (experiments, no CLI distribution)",
|
|
473
542
|
ProjectType.SAFETY_CRITICAL: "Safety-critical embedded (IEC 60204-1/62061/61508)",
|
|
543
|
+
# IP / Patent
|
|
544
|
+
ProjectType.PATENT_PROSECUTION: "Patent prosecution repository (USPTO IP lifecycle)",
|
|
545
|
+
# Modern web frameworks
|
|
546
|
+
ProjectType.NEXTJS_APP: "Next.js application (React + SSR/SSG)",
|
|
547
|
+
ProjectType.NUXT_APP: "Nuxt.js application (Vue + SSR/SSG)",
|
|
548
|
+
ProjectType.SVELTEKIT_APP: "SvelteKit application",
|
|
549
|
+
ProjectType.REMIX_APP: "Remix application (React + full-stack)",
|
|
550
|
+
ProjectType.ASTRO_SITE: "Astro site (static / SSR)",
|
|
474
551
|
}
|
|
475
552
|
|
|
476
553
|
_SECTION_REFS: dict[str, str] = {
|
|
@@ -113,6 +113,7 @@ class _MigrationRegistry:
|
|
|
113
113
|
m003_compliance_init,
|
|
114
114
|
m004_ledger_esdb,
|
|
115
115
|
m005_agent_run_tool,
|
|
116
|
+
m006_session_governance,
|
|
116
117
|
)
|
|
117
118
|
|
|
118
119
|
instances: list[Migration] = [
|
|
@@ -121,6 +122,7 @@ class _MigrationRegistry:
|
|
|
121
122
|
m003_compliance_init.ComplianceInitMigration(),
|
|
122
123
|
m004_ledger_esdb.LedgerEsdbMigration(),
|
|
123
124
|
m005_agent_run_tool.AgentRunToolMigration(),
|
|
125
|
+
m006_session_governance.SessionGovernanceMigration(),
|
|
124
126
|
]
|
|
125
127
|
instances.sort(key=lambda m: m.version)
|
|
126
128
|
self._migrations = instances
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 BitConcepts, LLC. All rights reserved.
|
|
3
|
+
"""M006 — Inject Session Governance Protocol into AGENTS.md.
|
|
4
|
+
|
|
5
|
+
What this migration does
|
|
6
|
+
------------------------
|
|
7
|
+
Adds the mandatory ``## Session Governance Protocol`` section to AGENTS.md
|
|
8
|
+
when it is absent. This section teaches any agent (Warp, Cursor, Claude,
|
|
9
|
+
GPT, or any other chat surface) to:
|
|
10
|
+
|
|
11
|
+
1. Run ``specsmith checkpoint`` at session start and emit the GOVERNANCE ANCHOR
|
|
12
|
+
as the first response.
|
|
13
|
+
2. Gate every code change behind ``specsmith preflight``.
|
|
14
|
+
3. Emit ``specsmith checkpoint`` every 8–10 turns as a heartbeat so governance
|
|
15
|
+
state survives context summarisation.
|
|
16
|
+
4. Include the GOVERNANCE ANCHOR at the top of any context summary.
|
|
17
|
+
5. Run ``specsmith save && specsmith kill-session`` at session end.
|
|
18
|
+
|
|
19
|
+
This is the most impactful upgrade for preventing silent governance drift in
|
|
20
|
+
long agentic sessions.
|
|
21
|
+
|
|
22
|
+
Non-destructive:
|
|
23
|
+
- AGENTS.md is backed up to ``.specsmith/agents.md.m006.bak`` before modification.
|
|
24
|
+
- The migration is idempotent: re-running it when the section is already present
|
|
25
|
+
is a no-op.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
from specsmith.migrations import Migration, MigrationResult
|
|
33
|
+
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
# Sentinel strings that indicate the section is already present
|
|
36
|
+
# ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
_SENTINELS = [
|
|
39
|
+
"specsmith checkpoint",
|
|
40
|
+
"Session Governance Protocol",
|
|
41
|
+
"GOVERNANCE ANCHOR",
|
|
42
|
+
"governance heartbeat",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
# Section text to inject
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
_SESSION_GOVERNANCE_SECTION = """
|
|
50
|
+
## Session Governance Protocol
|
|
51
|
+
|
|
52
|
+
This section is non-negotiable. Follow it in **every session**, in **every
|
|
53
|
+
chat application** (Warp, Cursor, Claude, GPT, or any other agent surface).
|
|
54
|
+
|
|
55
|
+
### Session start (run once, output result verbatim)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
specsmith kill-session 2>/dev/null || true # kill orphaned processes
|
|
59
|
+
specsmith audit --project-dir . # verify governance health
|
|
60
|
+
specsmith sync --project-dir . # confirm machine state
|
|
61
|
+
specsmith checkpoint --project-dir . # emit GOVERNANCE ANCHOR
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Output the `specsmith checkpoint` block verbatim as your first response.**
|
|
65
|
+
|
|
66
|
+
### Before every code change
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
specsmith preflight "<describe the change>" --json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `decision == "accepted"` → proceed; note the `work_item_id`.
|
|
73
|
+
- `decision == "needs_clarification"` → surface the `instruction` first.
|
|
74
|
+
- **Never make a code change without an accepted preflight.**
|
|
75
|
+
|
|
76
|
+
### Governance heartbeat (every 8–10 turns, or when context feels compressed)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
specsmith checkpoint --project-dir .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Output the GOVERNANCE ANCHOR block verbatim in your response, tagged:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
⎠ GOVERNANCE ANCHOR:
|
|
86
|
+
<paste checkpoint output here>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### When producing any context summary
|
|
90
|
+
|
|
91
|
+
1. Run `specsmith checkpoint` first.
|
|
92
|
+
2. Place the GOVERNANCE ANCHOR at the **top** of the summary.
|
|
93
|
+
3. Never omit phase, work items, or health status from a summary.
|
|
94
|
+
|
|
95
|
+
### Drift detection — if you cannot answer these from memory, you have drifted
|
|
96
|
+
|
|
97
|
+
- What is the current AEE phase?
|
|
98
|
+
- What work item is active?
|
|
99
|
+
- What was the last preflight decision?
|
|
100
|
+
- Is the audit currently healthy?
|
|
101
|
+
|
|
102
|
+
If any answer is unknown: **run `specsmith checkpoint` and re-anchor immediately.**
|
|
103
|
+
|
|
104
|
+
### Session end
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
specsmith save --project-dir . # ESDB backup + commit + push
|
|
108
|
+
specsmith kill-session # stop governance-serve and tracked processes
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Never end a session with uncommitted governance changes.
|
|
112
|
+
|
|
113
|
+
### Quick reference
|
|
114
|
+
|
|
115
|
+
| When | Command |
|
|
116
|
+
|---|---|
|
|
117
|
+
| Session start | `specsmith audit && specsmith sync && specsmith checkpoint` |
|
|
118
|
+
| Before any code change | `specsmith preflight "<intent>" --json` |
|
|
119
|
+
| Every 8–10 turns | `specsmith checkpoint` (output verbatim) |
|
|
120
|
+
| Context summary | Checkpoint output at top |
|
|
121
|
+
| Session end | `specsmith save && specsmith kill-session` |
|
|
122
|
+
| Drift detected | `specsmith checkpoint` immediately |
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class SessionGovernanceMigration(Migration):
|
|
127
|
+
version = 6
|
|
128
|
+
title = "Inject Session Governance Protocol into AGENTS.md"
|
|
129
|
+
description = (
|
|
130
|
+
"Adds the mandatory Session Governance Protocol section to AGENTS.md so "
|
|
131
|
+
"any agent (Warp, Cursor, Claude, GPT) knows to emit specsmith checkpoint "
|
|
132
|
+
"at session start, gate changes behind preflight, and maintain heartbeat "
|
|
133
|
+
"anchors every 8-10 turns to prevent silent governance drift. "
|
|
134
|
+
"Non-destructive — AGENTS.md is backed up before modification."
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def run(self, root: Path, *, dry_run: bool = False) -> MigrationResult:
|
|
138
|
+
result = MigrationResult(version=self.version, title=self.title, dry_run=dry_run)
|
|
139
|
+
messages: list[str] = []
|
|
140
|
+
|
|
141
|
+
agents_md = root / "AGENTS.md"
|
|
142
|
+
specsmith_dir = root / ".specsmith"
|
|
143
|
+
|
|
144
|
+
if not agents_md.exists():
|
|
145
|
+
messages.append("AGENTS.md not found — skipping.")
|
|
146
|
+
result.message = " ".join(messages)
|
|
147
|
+
return result
|
|
148
|
+
|
|
149
|
+
current = agents_md.read_text(encoding="utf-8", errors="replace")
|
|
150
|
+
|
|
151
|
+
# Idempotency check — any sentinel means the section is present
|
|
152
|
+
if any(sentinel in current for sentinel in _SENTINELS):
|
|
153
|
+
messages.append("AGENTS.md already contains Session Governance Protocol — skipping.")
|
|
154
|
+
result.message = " ".join(messages)
|
|
155
|
+
return result
|
|
156
|
+
|
|
157
|
+
if dry_run:
|
|
158
|
+
messages.append(
|
|
159
|
+
"Would inject Session Governance Protocol section into AGENTS.md "
|
|
160
|
+
"and back up to .specsmith/agents.md.m006.bak."
|
|
161
|
+
)
|
|
162
|
+
result.files_created.append(".specsmith/agents.md.m006.bak")
|
|
163
|
+
result.files_modified.append("AGENTS.md")
|
|
164
|
+
result.message = " ".join(messages)
|
|
165
|
+
return result
|
|
166
|
+
|
|
167
|
+
# Back up
|
|
168
|
+
specsmith_dir.mkdir(parents=True, exist_ok=True)
|
|
169
|
+
bak = specsmith_dir / "agents.md.m006.bak"
|
|
170
|
+
bak.write_text(current, encoding="utf-8")
|
|
171
|
+
result.files_created.append(".specsmith/agents.md.m006.bak")
|
|
172
|
+
|
|
173
|
+
# Inject the section — find the best insertion point.
|
|
174
|
+
# Strategy: insert BEFORE the first existing ## section after the header
|
|
175
|
+
# (which is typically ## Session Bootstrap), so the governance protocol
|
|
176
|
+
# is at the very top of agent instructions.
|
|
177
|
+
insertion_marker = "## Session Bootstrap"
|
|
178
|
+
if insertion_marker in current:
|
|
179
|
+
# Insert the governance section AFTER Session Bootstrap (it depends
|
|
180
|
+
# on Bootstrap completing first).
|
|
181
|
+
bootstrap_pos = current.find(insertion_marker)
|
|
182
|
+
# Find the next ## heading after Bootstrap to insert before it
|
|
183
|
+
next_section_pos = current.find("\n## ", bootstrap_pos + len(insertion_marker))
|
|
184
|
+
if next_section_pos != -1:
|
|
185
|
+
# Insert between Bootstrap section and whatever comes next
|
|
186
|
+
patched = (
|
|
187
|
+
current[:next_section_pos]
|
|
188
|
+
+ "\n"
|
|
189
|
+
+ _SESSION_GOVERNANCE_SECTION.strip()
|
|
190
|
+
+ "\n"
|
|
191
|
+
+ current[next_section_pos:]
|
|
192
|
+
)
|
|
193
|
+
else:
|
|
194
|
+
# Bootstrap is the last section — append after it
|
|
195
|
+
patched = current.rstrip() + "\n\n" + _SESSION_GOVERNANCE_SECTION.strip() + "\n"
|
|
196
|
+
else:
|
|
197
|
+
# No Bootstrap section — just append
|
|
198
|
+
separator = "\n\n---\n" if not current.endswith("\n\n") else "\n---\n"
|
|
199
|
+
patched = current + separator + _SESSION_GOVERNANCE_SECTION.strip() + "\n"
|
|
200
|
+
|
|
201
|
+
agents_md.write_text(patched, encoding="utf-8")
|
|
202
|
+
result.files_modified.append("AGENTS.md")
|
|
203
|
+
messages.append(
|
|
204
|
+
"Injected Session Governance Protocol section into AGENTS.md "
|
|
205
|
+
"(original backed up to .specsmith/agents.md.m006.bak)."
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
result.message = " ".join(messages)
|
|
209
|
+
return result
|
|
210
|
+
|
|
211
|
+
def rollback(self, root: Path) -> MigrationResult:
|
|
212
|
+
"""Restore AGENTS.md from the M006 backup."""
|
|
213
|
+
result = MigrationResult(version=self.version, title=self.title)
|
|
214
|
+
messages: list[str] = []
|
|
215
|
+
|
|
216
|
+
specsmith_dir = root / ".specsmith"
|
|
217
|
+
bak = specsmith_dir / "agents.md.m006.bak"
|
|
218
|
+
agents_md = root / "AGENTS.md"
|
|
219
|
+
|
|
220
|
+
if bak.exists():
|
|
221
|
+
agents_md.write_text(
|
|
222
|
+
bak.read_text(encoding="utf-8", errors="replace"), encoding="utf-8"
|
|
223
|
+
)
|
|
224
|
+
messages.append("Restored AGENTS.md from .specsmith/agents.md.m006.bak.")
|
|
225
|
+
result.files_modified.append("AGENTS.md")
|
|
226
|
+
else:
|
|
227
|
+
messages.append("No AGENTS.md backup found — cannot restore.")
|
|
228
|
+
|
|
229
|
+
result.message = " ".join(messages)
|
|
230
|
+
return result
|