specsmith 0.10.1.dev272__tar.gz → 0.10.1.dev277__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.10.1.dev272/src/specsmith.egg-info → specsmith-0.10.1.dev277}/PKG-INFO +22 -48
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/README.md +21 -47
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/pyproject.toml +1 -1
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/cli.py +107 -0
- specsmith-0.10.1.dev277/src/specsmith/editor.py +277 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277/src/specsmith.egg-info}/PKG-INFO +22 -48
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith.egg-info/SOURCES.txt +1 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_nexus.py +8 -3
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/LICENSE +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/setup.cfg +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/belief.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/certainty.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/failure_graph.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/py.typed +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/recovery.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/session.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/stress_tester.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/epistemic/trace.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/__main__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/broker.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/chat_runner.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/cleanup.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/core.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/endpoints.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/events.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/execution_profiles.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/fallback.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/indexer.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/mcp.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/memory.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/model_intelligence.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/orchestrator.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/permissions.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/profiles.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/provider_registry.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/repl.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/router.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/rules.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/runner.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/safety.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/suggester.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/tools.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/verifier.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/agent/voice.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/architect.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/auditor.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/auth.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/block_export.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/commands/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/commands/intelligence.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/compressor.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/config.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/console_utils.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/credit_analyzer.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/credits.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/base.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/citations.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/fpd.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/odp.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/patentsview.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/pfw.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/ppubs.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/datasources/ptab.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/differ.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/doctor.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/drive.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/epistemic/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/epistemic/belief.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/epistemic/certainty.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/epistemic/failure_graph.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/epistemic/recovery.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/epistemic/stress_tester.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/executor.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/exporter.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/governance_logic.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/app.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/main_window.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/session_tab.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/theme.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/widgets/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/widgets/chat_view.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/widgets/input_bar.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/widgets/provider_bar.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/widgets/token_meter.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/widgets/tool_panel.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/widgets/update_checker.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/gui/worker.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/history_search.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/importer.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/instinct.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/agent_skill.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/aider.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/base.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/claude_code.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/copilot.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/cursor.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/gemini.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/integrations/windsurf.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/languages.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/ledger.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/patent.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/paths.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/phase.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/plugins.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/profiles.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/rate_limits.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/releaser.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/requirements.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/requirements_parser.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/retrieval.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/safe_write.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/scaffolder.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/serve.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/session.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/skills.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/sync.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/agents.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/contributing.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/license-MIT.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/community/security.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/editorconfig.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/gitattributes.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/gitignore.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/go/go.mod.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/go/main.go.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/roles.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/rules.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/governance/verification.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/js/package.json.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/ledger.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/python/cli.py.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/python/init.py.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/readme.md.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/rust/main.rs.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/tool_installer.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/toolrules.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/tools.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/trace.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/updater.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/upgrader.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/validator.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/vcs/__init__.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/vcs/base.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/vcs/bitbucket.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/vcs/github.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/vcs/gitlab.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/vcs_commands.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/wireframes.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith/workspace.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith.egg-info/dependency_links.txt +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith.egg-info/entry_points.txt +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith.egg-info/requires.txt +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/src/specsmith.egg-info/top_level.txt +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_CMD_001.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_agent_profiles.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_agent_runner_ready.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_auditor.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_chat_diff_decision.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_chat_runner_openai_compat.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_chat_stdin_protocol.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_cli.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_cli_workflows_history_drive.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_compressor.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_e2e_nexus.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_endpoints_cli.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_endpoints_store.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_epistemic.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_fallback_chain.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_importer.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_integrations.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_mcp_client.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_permissions.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_phase1_4_new.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_phase34_completion.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_rate_limits.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_scaffolder.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_skill_marketplace.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_smoke.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_suggester.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_tools.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_validator.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_vcs.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/tests/test_warp_parity.py +0 -0
- {specsmith-0.10.1.dev272 → specsmith-0.10.1.dev277}/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.10.1.
|
|
3
|
+
Version: 0.10.1.dev277
|
|
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
|
|
@@ -78,8 +78,6 @@ Dynamic: license-file
|
|
|
78
78
|
[](https://pypi.org/project/specsmith/)
|
|
79
79
|
[](https://www.python.org/downloads/)
|
|
80
80
|
[](LICENSE)
|
|
81
|
-
[](https://github.com/BitConcepts/specsmith-vscode)
|
|
82
|
-
|
|
83
81
|
**Applied Epistemic Engineering toolkit for AI-assisted development.**
|
|
84
82
|
|
|
85
83
|
> Intelligence proposes. Constraints decide. The ledger remembers.
|
|
@@ -142,23 +140,15 @@ specsmith phase set requirements # jump to a specific phase
|
|
|
142
140
|
specsmith phase list # list all phases
|
|
143
141
|
```
|
|
144
142
|
|
|
145
|
-
The current phase is persisted in `scaffold.yml` as `aee_phase` and displayed in the
|
|
146
|
-
|
|
147
|
-
and a readiness percentage.
|
|
143
|
+
The current phase is persisted in `scaffold.yml` as `aee_phase` and displayed in the
|
|
144
|
+
Kairos Governance page. Each phase has a checklist of file/command criteria, recommended
|
|
145
|
+
commands, and a readiness percentage.
|
|
148
146
|
|
|
149
147
|
---
|
|
150
148
|
|
|
151
149
|
## Install
|
|
152
150
|
|
|
153
|
-
**Recommended — via
|
|
154
|
-
|
|
155
|
-
1. Install the [specsmith AEE Workbench](https://github.com/BitConcepts/specsmith-vscode) VS Code extension
|
|
156
|
-
2. Open `Ctrl+Shift+,` (⚙ specsmith Settings)
|
|
157
|
-
3. Click **🔒 Create Environment** — creates `~/.specsmith/venv/` with specsmith + your provider packages
|
|
158
|
-
|
|
159
|
-
The extension uses this environment for all agent sessions and terminal commands.
|
|
160
|
-
|
|
161
|
-
**Or via pipx (system-wide):**
|
|
151
|
+
**Recommended — via pipx (works with Kairos, any terminal, and CI):**
|
|
162
152
|
|
|
163
153
|
```bash
|
|
164
154
|
pipx install specsmith # core CLI + epistemic library
|
|
@@ -316,36 +306,20 @@ requirement, test, and work-item identifiers Specsmith assigned.
|
|
|
316
306
|
|
|
317
307
|
---
|
|
318
308
|
|
|
319
|
-
##
|
|
309
|
+
## Kairos — Flagship Terminal Client
|
|
320
310
|
|
|
321
|
-
|
|
311
|
+
**[Kairos](https://github.com/BitConcepts/kairos)** is the recommended terminal client for specsmith.
|
|
312
|
+
Kairos spawns specsmith as a managed governance child process at startup and routes all
|
|
313
|
+
preflight, verify, and BYOE proxy calls through it. The Governance settings page shows live
|
|
314
|
+
specsmith status, version, and one-click update.
|
|
322
315
|
|
|
323
|
-
```
|
|
324
|
-
#
|
|
325
|
-
|
|
326
|
-
# Project Settings: Ctrl+Shift+G (⚙ Project Settings — per-project)
|
|
316
|
+
```bash
|
|
317
|
+
# Kairos starts specsmith automatically; or run manually:
|
|
318
|
+
specsmith governance-serve --port 7700 --project-dir .
|
|
327
319
|
```
|
|
328
320
|
|
|
329
|
-
**
|
|
330
|
-
|
|
331
|
-
and **⚙ Project Settings** (per-project: scaffold, tools, files, actions, execution)
|
|
332
|
-
- **Global environment management** — `~/.specsmith/venv/` with Create / Update / Rebuild / Delete;
|
|
333
|
-
persistent restart banner; Remove System Installs cleanup button
|
|
334
|
-
- **VCS context at session start** — git status + recent commits shown in chat and in system prompt
|
|
335
|
-
- **Execution profiles** — safe / standard / open / admin; custom allow/block command lists
|
|
336
|
-
- **AEE phase indicator** — shows current phase with readiness %, Next Phase button, phase selector
|
|
337
|
-
- **AI agent sessions** — independent process per project, JSONL bridge, chat with file injection
|
|
338
|
-
- **AG2 agent shell** — Planner/Builder/Verifier agents over Ollama in Actions tab
|
|
339
|
-
- **Agent tab** — per-project provider/model/context/iteration config (overrides global defaults)
|
|
340
|
-
- **Live model listing** — Anthropic, OpenAI, Gemini, Mistral, local Ollama (GPU-aware)
|
|
341
|
-
- **Ollama model catalog** — 16 models, 4 tiers, GPU-aware recommendations, filter by installed/available
|
|
342
|
-
- **Ollama integration** — model manager (update/remove/update-all), version check, upgrade
|
|
343
|
-
- **FPGA/HDL tool support** — vivado, gtkwave, vsg, ghdl, verilator, yosys, nextpnr, and 15 more
|
|
344
|
-
- **Tool installer** — scan installed tools; one-click install via winget/brew/apt for missing tools
|
|
345
|
-
- **API key management** — stored in OS credential store (Windows Credential Manager / macOS Keychain)
|
|
346
|
-
- **Update checker** — PyPI version check, auto-checks on panel open, release channel selector
|
|
347
|
-
|
|
348
|
-
**[→ specsmith-vscode on GitHub](https://github.com/BitConcepts/specsmith-vscode)**
|
|
321
|
+
The VS Code extension (`specsmith-vscode`) has been **deprecated** in favour of Kairos.
|
|
322
|
+
Use `pipx install specsmith` for standalone CLI usage from any terminal.
|
|
349
323
|
|
|
350
324
|
---
|
|
351
325
|
|
|
@@ -353,7 +327,7 @@ The **specsmith AEE Workbench** VS Code extension is the flagship client:
|
|
|
353
327
|
|
|
354
328
|
specsmith is open source and built by a small team. Every bit of support helps:
|
|
355
329
|
|
|
356
|
-
- ⭐ **Star** [specsmith](https://github.com/BitConcepts/specsmith) and [
|
|
330
|
+
- ⭐ **Star** [specsmith](https://github.com/BitConcepts/specsmith) and [kairos](https://github.com/BitConcepts/kairos) on GitHub
|
|
357
331
|
- 📣 **Tell your friends and colleagues** — word of mouth is our best marketing
|
|
358
332
|
- 🐛 **Report bugs** via [GitHub Issues](https://github.com/BitConcepts/specsmith/issues) — even small ones help
|
|
359
333
|
- 💡 **Suggest features** via [GitHub Discussions](https://github.com/BitConcepts/specsmith/discussions) — we read every suggestion
|
|
@@ -376,8 +350,8 @@ specsmith ollama suggest requirements # task-based recommendations
|
|
|
376
350
|
specsmith ollama list # show installed models
|
|
377
351
|
```
|
|
378
352
|
|
|
379
|
-
GPU-aware context sizing
|
|
380
|
-
Override
|
|
353
|
+
GPU-aware context sizing: 4K/8K/16K/32K tokens based on detected VRAM.
|
|
354
|
+
Override via `SPECSMITH_OLLAMA_CONTEXT_LENGTH` env var or `ollama.context_length` in `.specsmith/config.yml`.
|
|
381
355
|
|
|
382
356
|
---
|
|
383
357
|
|
|
@@ -478,20 +452,20 @@ Use cases: linguistics research, compliance pipelines, AI alignment, patent pros
|
|
|
478
452
|
|
|
479
453
|
specsmith governs itself — the specsmith repo is a specsmith-managed project. Run `specsmith audit`
|
|
480
454
|
in this repo to check its governance health. This means every feature we add to specsmith is
|
|
481
|
-
immediately dogfooded on specsmith itself.
|
|
482
|
-
is
|
|
455
|
+
immediately dogfooded on specsmith itself. [Kairos](https://github.com/BitConcepts/kairos)
|
|
456
|
+
is the companion terminal and flagship client.
|
|
483
457
|
|
|
484
458
|
## Documentation
|
|
485
459
|
|
|
486
460
|
**[specsmith.readthedocs.io](https://specsmith.readthedocs.io)** — Full manual: AEE primer,
|
|
487
|
-
command reference, project types, tool registry, governance model, Ollama guide,
|
|
461
|
+
command reference, project types, tool registry, governance model, Ollama guide, Kairos integration.
|
|
488
462
|
|
|
489
463
|
## Links
|
|
490
464
|
|
|
491
465
|
- [PyPI](https://pypi.org/project/specsmith/)
|
|
492
466
|
- [Documentation](https://specsmith.readthedocs.io)
|
|
493
467
|
- [Changelog](CHANGELOG.md)
|
|
494
|
-
- [
|
|
468
|
+
- [Kairos terminal client](https://github.com/BitConcepts/kairos)
|
|
495
469
|
- [Contributing](CONTRIBUTING.md)
|
|
496
470
|
- [Security](SECURITY.md)
|
|
497
471
|
|
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
[](https://pypi.org/project/specsmith/)
|
|
7
7
|
[](https://www.python.org/downloads/)
|
|
8
8
|
[](LICENSE)
|
|
9
|
-
[](https://github.com/BitConcepts/specsmith-vscode)
|
|
10
|
-
|
|
11
9
|
**Applied Epistemic Engineering toolkit for AI-assisted development.**
|
|
12
10
|
|
|
13
11
|
> Intelligence proposes. Constraints decide. The ledger remembers.
|
|
@@ -70,23 +68,15 @@ specsmith phase set requirements # jump to a specific phase
|
|
|
70
68
|
specsmith phase list # list all phases
|
|
71
69
|
```
|
|
72
70
|
|
|
73
|
-
The current phase is persisted in `scaffold.yml` as `aee_phase` and displayed in the
|
|
74
|
-
|
|
75
|
-
and a readiness percentage.
|
|
71
|
+
The current phase is persisted in `scaffold.yml` as `aee_phase` and displayed in the
|
|
72
|
+
Kairos Governance page. Each phase has a checklist of file/command criteria, recommended
|
|
73
|
+
commands, and a readiness percentage.
|
|
76
74
|
|
|
77
75
|
---
|
|
78
76
|
|
|
79
77
|
## Install
|
|
80
78
|
|
|
81
|
-
**Recommended — via
|
|
82
|
-
|
|
83
|
-
1. Install the [specsmith AEE Workbench](https://github.com/BitConcepts/specsmith-vscode) VS Code extension
|
|
84
|
-
2. Open `Ctrl+Shift+,` (⚙ specsmith Settings)
|
|
85
|
-
3. Click **🔒 Create Environment** — creates `~/.specsmith/venv/` with specsmith + your provider packages
|
|
86
|
-
|
|
87
|
-
The extension uses this environment for all agent sessions and terminal commands.
|
|
88
|
-
|
|
89
|
-
**Or via pipx (system-wide):**
|
|
79
|
+
**Recommended — via pipx (works with Kairos, any terminal, and CI):**
|
|
90
80
|
|
|
91
81
|
```bash
|
|
92
82
|
pipx install specsmith # core CLI + epistemic library
|
|
@@ -244,36 +234,20 @@ requirement, test, and work-item identifiers Specsmith assigned.
|
|
|
244
234
|
|
|
245
235
|
---
|
|
246
236
|
|
|
247
|
-
##
|
|
237
|
+
## Kairos — Flagship Terminal Client
|
|
248
238
|
|
|
249
|
-
|
|
239
|
+
**[Kairos](https://github.com/BitConcepts/kairos)** is the recommended terminal client for specsmith.
|
|
240
|
+
Kairos spawns specsmith as a managed governance child process at startup and routes all
|
|
241
|
+
preflight, verify, and BYOE proxy calls through it. The Governance settings page shows live
|
|
242
|
+
specsmith status, version, and one-click update.
|
|
250
243
|
|
|
251
|
-
```
|
|
252
|
-
#
|
|
253
|
-
|
|
254
|
-
# Project Settings: Ctrl+Shift+G (⚙ Project Settings — per-project)
|
|
244
|
+
```bash
|
|
245
|
+
# Kairos starts specsmith automatically; or run manually:
|
|
246
|
+
specsmith governance-serve --port 7700 --project-dir .
|
|
255
247
|
```
|
|
256
248
|
|
|
257
|
-
**
|
|
258
|
-
|
|
259
|
-
and **⚙ Project Settings** (per-project: scaffold, tools, files, actions, execution)
|
|
260
|
-
- **Global environment management** — `~/.specsmith/venv/` with Create / Update / Rebuild / Delete;
|
|
261
|
-
persistent restart banner; Remove System Installs cleanup button
|
|
262
|
-
- **VCS context at session start** — git status + recent commits shown in chat and in system prompt
|
|
263
|
-
- **Execution profiles** — safe / standard / open / admin; custom allow/block command lists
|
|
264
|
-
- **AEE phase indicator** — shows current phase with readiness %, Next Phase button, phase selector
|
|
265
|
-
- **AI agent sessions** — independent process per project, JSONL bridge, chat with file injection
|
|
266
|
-
- **AG2 agent shell** — Planner/Builder/Verifier agents over Ollama in Actions tab
|
|
267
|
-
- **Agent tab** — per-project provider/model/context/iteration config (overrides global defaults)
|
|
268
|
-
- **Live model listing** — Anthropic, OpenAI, Gemini, Mistral, local Ollama (GPU-aware)
|
|
269
|
-
- **Ollama model catalog** — 16 models, 4 tiers, GPU-aware recommendations, filter by installed/available
|
|
270
|
-
- **Ollama integration** — model manager (update/remove/update-all), version check, upgrade
|
|
271
|
-
- **FPGA/HDL tool support** — vivado, gtkwave, vsg, ghdl, verilator, yosys, nextpnr, and 15 more
|
|
272
|
-
- **Tool installer** — scan installed tools; one-click install via winget/brew/apt for missing tools
|
|
273
|
-
- **API key management** — stored in OS credential store (Windows Credential Manager / macOS Keychain)
|
|
274
|
-
- **Update checker** — PyPI version check, auto-checks on panel open, release channel selector
|
|
275
|
-
|
|
276
|
-
**[→ specsmith-vscode on GitHub](https://github.com/BitConcepts/specsmith-vscode)**
|
|
249
|
+
The VS Code extension (`specsmith-vscode`) has been **deprecated** in favour of Kairos.
|
|
250
|
+
Use `pipx install specsmith` for standalone CLI usage from any terminal.
|
|
277
251
|
|
|
278
252
|
---
|
|
279
253
|
|
|
@@ -281,7 +255,7 @@ The **specsmith AEE Workbench** VS Code extension is the flagship client:
|
|
|
281
255
|
|
|
282
256
|
specsmith is open source and built by a small team. Every bit of support helps:
|
|
283
257
|
|
|
284
|
-
- ⭐ **Star** [specsmith](https://github.com/BitConcepts/specsmith) and [
|
|
258
|
+
- ⭐ **Star** [specsmith](https://github.com/BitConcepts/specsmith) and [kairos](https://github.com/BitConcepts/kairos) on GitHub
|
|
285
259
|
- 📣 **Tell your friends and colleagues** — word of mouth is our best marketing
|
|
286
260
|
- 🐛 **Report bugs** via [GitHub Issues](https://github.com/BitConcepts/specsmith/issues) — even small ones help
|
|
287
261
|
- 💡 **Suggest features** via [GitHub Discussions](https://github.com/BitConcepts/specsmith/discussions) — we read every suggestion
|
|
@@ -304,8 +278,8 @@ specsmith ollama suggest requirements # task-based recommendations
|
|
|
304
278
|
specsmith ollama list # show installed models
|
|
305
279
|
```
|
|
306
280
|
|
|
307
|
-
GPU-aware context sizing
|
|
308
|
-
Override
|
|
281
|
+
GPU-aware context sizing: 4K/8K/16K/32K tokens based on detected VRAM.
|
|
282
|
+
Override via `SPECSMITH_OLLAMA_CONTEXT_LENGTH` env var or `ollama.context_length` in `.specsmith/config.yml`.
|
|
309
283
|
|
|
310
284
|
---
|
|
311
285
|
|
|
@@ -406,20 +380,20 @@ Use cases: linguistics research, compliance pipelines, AI alignment, patent pros
|
|
|
406
380
|
|
|
407
381
|
specsmith governs itself — the specsmith repo is a specsmith-managed project. Run `specsmith audit`
|
|
408
382
|
in this repo to check its governance health. This means every feature we add to specsmith is
|
|
409
|
-
immediately dogfooded on specsmith itself.
|
|
410
|
-
is
|
|
383
|
+
immediately dogfooded on specsmith itself. [Kairos](https://github.com/BitConcepts/kairos)
|
|
384
|
+
is the companion terminal and flagship client.
|
|
411
385
|
|
|
412
386
|
## Documentation
|
|
413
387
|
|
|
414
388
|
**[specsmith.readthedocs.io](https://specsmith.readthedocs.io)** — Full manual: AEE primer,
|
|
415
|
-
command reference, project types, tool registry, governance model, Ollama guide,
|
|
389
|
+
command reference, project types, tool registry, governance model, Ollama guide, Kairos integration.
|
|
416
390
|
|
|
417
391
|
## Links
|
|
418
392
|
|
|
419
393
|
- [PyPI](https://pypi.org/project/specsmith/)
|
|
420
394
|
- [Documentation](https://specsmith.readthedocs.io)
|
|
421
395
|
- [Changelog](CHANGELOG.md)
|
|
422
|
-
- [
|
|
396
|
+
- [Kairos terminal client](https://github.com/BitConcepts/kairos)
|
|
423
397
|
- [Contributing](CONTRIBUTING.md)
|
|
424
398
|
- [Security](SECURITY.md)
|
|
425
399
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specsmith"
|
|
7
|
-
version = "0.10.1.
|
|
7
|
+
version = "0.10.1.dev277"
|
|
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"
|
|
@@ -5066,6 +5066,113 @@ def instinct_import(file_path: str, project_dir: str) -> None:
|
|
|
5066
5066
|
main.add_command(instinct_group)
|
|
5067
5067
|
|
|
5068
5068
|
|
|
5069
|
+
# ---------------------------------------------------------------------------
|
|
5070
|
+
# specsmith config — global configuration (editor, etc.)
|
|
5071
|
+
# ---------------------------------------------------------------------------
|
|
5072
|
+
|
|
5073
|
+
|
|
5074
|
+
@main.group(name="config")
|
|
5075
|
+
def config_group() -> None:
|
|
5076
|
+
"""Manage global specsmith configuration.
|
|
5077
|
+
|
|
5078
|
+
Settings are stored in ``~/.specsmith/config.toml``.
|
|
5079
|
+
"""
|
|
5080
|
+
|
|
5081
|
+
|
|
5082
|
+
@config_group.command(name="editor")
|
|
5083
|
+
@click.argument("command", required=False, default=None)
|
|
5084
|
+
@click.option(
|
|
5085
|
+
"--list",
|
|
5086
|
+
"list_editors",
|
|
5087
|
+
is_flag=True,
|
|
5088
|
+
default=False,
|
|
5089
|
+
help="List all editors detected on this machine.",
|
|
5090
|
+
)
|
|
5091
|
+
@click.option(
|
|
5092
|
+
"--set",
|
|
5093
|
+
"set_cmd",
|
|
5094
|
+
default="",
|
|
5095
|
+
help="Set the preferred editor (saved to ~/.specsmith/config.toml).",
|
|
5096
|
+
)
|
|
5097
|
+
def config_editor_cmd(
|
|
5098
|
+
command: str | None,
|
|
5099
|
+
list_editors: bool,
|
|
5100
|
+
set_cmd: str,
|
|
5101
|
+
) -> None:
|
|
5102
|
+
"""Manage the editor used by specsmith to open files.
|
|
5103
|
+
|
|
5104
|
+
\b
|
|
5105
|
+
Resolution order:
|
|
5106
|
+
1. $EDITOR environment variable (highest priority)
|
|
5107
|
+
2. 'editor' key in ~/.specsmith/config.toml
|
|
5108
|
+
3. Auto-detected editor for this platform
|
|
5109
|
+
|
|
5110
|
+
\b
|
|
5111
|
+
Examples:
|
|
5112
|
+
specsmith config editor # show currently resolved editor
|
|
5113
|
+
specsmith config editor --list # show all detected editors
|
|
5114
|
+
specsmith config editor --set code # set VS Code as preferred editor
|
|
5115
|
+
"""
|
|
5116
|
+
from specsmith.editor import (
|
|
5117
|
+
list_detected_editors,
|
|
5118
|
+
resolve_editor,
|
|
5119
|
+
set_editor_preference,
|
|
5120
|
+
)
|
|
5121
|
+
|
|
5122
|
+
# --set flag takes precedence
|
|
5123
|
+
if set_cmd or (command and not list_editors):
|
|
5124
|
+
target = set_cmd or command or ""
|
|
5125
|
+
if not target:
|
|
5126
|
+
console.print("[red]Error:[/red] specify a command, e.g. --set code")
|
|
5127
|
+
raise SystemExit(1)
|
|
5128
|
+
saved_path = set_editor_preference(target)
|
|
5129
|
+
console.print(
|
|
5130
|
+
f"[green]\u2713[/green] Saved editor preference: [bold]{target}[/bold]\n"
|
|
5131
|
+
f" Config: {saved_path}"
|
|
5132
|
+
)
|
|
5133
|
+
return
|
|
5134
|
+
|
|
5135
|
+
if list_editors:
|
|
5136
|
+
candidates = list_detected_editors()
|
|
5137
|
+
if not candidates:
|
|
5138
|
+
console.print("[yellow]No editors detected on this machine.[/yellow]")
|
|
5139
|
+
console.print(
|
|
5140
|
+
" Install VS Code, Neovim, or another editor and re-run, or set $EDITOR manually."
|
|
5141
|
+
)
|
|
5142
|
+
return
|
|
5143
|
+
console.print("[bold]Detected editors:[/bold]\n")
|
|
5144
|
+
for c in candidates:
|
|
5145
|
+
path_hint = f" [dim]({c.path})[/dim]" if c.path else ""
|
|
5146
|
+
console.print(f" [cyan]{c.command:<20}[/cyan] {c.name}{path_hint}")
|
|
5147
|
+
return
|
|
5148
|
+
|
|
5149
|
+
# Default: show the currently resolved editor
|
|
5150
|
+
import os
|
|
5151
|
+
|
|
5152
|
+
env_val = os.environ.get("EDITOR", "").strip()
|
|
5153
|
+
resolved = resolve_editor()
|
|
5154
|
+
|
|
5155
|
+
console.print("[bold]Editor configuration[/bold]\n")
|
|
5156
|
+
if env_val:
|
|
5157
|
+
console.print(" Source: [green]$EDITOR[/green] environment variable")
|
|
5158
|
+
console.print(f" Command: [bold]{env_val}[/bold]")
|
|
5159
|
+
elif resolved:
|
|
5160
|
+
console.print(" Source: auto-detected")
|
|
5161
|
+
console.print(f" Command: [bold]{resolved}[/bold]")
|
|
5162
|
+
else:
|
|
5163
|
+
console.print(" [yellow]No editor resolved.[/yellow]")
|
|
5164
|
+
console.print(" Set $EDITOR or run [bold]specsmith config editor --set <command>[/bold].")
|
|
5165
|
+
console.print()
|
|
5166
|
+
console.print(
|
|
5167
|
+
" [dim]Override: set $EDITOR, or run "
|
|
5168
|
+
"'specsmith config editor --set <cmd>' to persist.[/dim]"
|
|
5169
|
+
)
|
|
5170
|
+
console.print(" [dim]List available editors: 'specsmith config editor --list'[/dim]")
|
|
5171
|
+
|
|
5172
|
+
|
|
5173
|
+
main.add_command(config_group)
|
|
5174
|
+
|
|
5175
|
+
|
|
5069
5176
|
# ---------------------------------------------------------------------------
|
|
5070
5177
|
# Kill-switch / emergency stop (REG-005)
|
|
5071
5178
|
# ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 BitConcepts, LLC. All rights reserved.
|
|
3
|
+
"""Cross-platform $EDITOR auto-detection for specsmith.
|
|
4
|
+
|
|
5
|
+
Resolution order (highest to lowest priority):
|
|
6
|
+
1. ``$EDITOR`` environment variable
|
|
7
|
+
2. ``editor`` key in ``~/.specsmith/config.toml`` or project ``.specsmith/config.yml``
|
|
8
|
+
3. Auto-detection: probe PATH + well-known install locations per platform
|
|
9
|
+
|
|
10
|
+
Usage::
|
|
11
|
+
|
|
12
|
+
from specsmith.editor import resolve_editor, list_detected_editors, set_editor_preference
|
|
13
|
+
|
|
14
|
+
# What will specsmith use to open files?
|
|
15
|
+
editor = resolve_editor() # e.g. "code", "notepad++", "nvim"
|
|
16
|
+
|
|
17
|
+
# Show all detected editors on this machine:
|
|
18
|
+
editors = list_detected_editors() # list of (name, path) tuples
|
|
19
|
+
|
|
20
|
+
# Persist a preference:
|
|
21
|
+
set_editor_preference("code") # writes to ~/.specsmith/config.toml
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import os
|
|
27
|
+
import platform
|
|
28
|
+
import shutil
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
from typing import NamedTuple
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"EditorCandidate",
|
|
34
|
+
"list_detected_editors",
|
|
35
|
+
"resolve_editor",
|
|
36
|
+
"set_editor_preference",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
# Data model
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class EditorCandidate(NamedTuple):
|
|
45
|
+
"""A discovered editor."""
|
|
46
|
+
|
|
47
|
+
name: str
|
|
48
|
+
"""Short display name (e.g. 'VS Code', 'Notepad++')."""
|
|
49
|
+
command: str
|
|
50
|
+
"""The executable / command to invoke (e.g. 'code', 'notepad++')."""
|
|
51
|
+
path: str | None
|
|
52
|
+
"""Resolved absolute path, or None if only found via PATH probe."""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ---------------------------------------------------------------------------
|
|
56
|
+
# Platform-specific candidate lists
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
#: Ordered list of (display_name, command) pairs for each platform.
|
|
60
|
+
#: The first entry that resolves wins for auto-detection.
|
|
61
|
+
_WINDOWS_CANDIDATES: list[tuple[str, str | list[str]]] = [
|
|
62
|
+
# VS Code (most popular cross-platform)
|
|
63
|
+
("VS Code", "code"),
|
|
64
|
+
# Cursor (AI-first VS Code fork)
|
|
65
|
+
("Cursor", "cursor"),
|
|
66
|
+
# Notepad++ — check common install paths since it's not always on PATH
|
|
67
|
+
("Notepad++", r"%LOCALAPPDATA%\Programs\Notepad++\notepad++.exe"),
|
|
68
|
+
("Notepad++", r"%PROGRAMFILES%\Notepad++\notepad++.exe"),
|
|
69
|
+
("Notepad++", r"%PROGRAMFILES(X86)%\Notepad++\notepad++.exe"),
|
|
70
|
+
("Notepad++", "notepad++"),
|
|
71
|
+
# Neovim (scoop / choco)
|
|
72
|
+
("Neovim", "nvim"),
|
|
73
|
+
# Vim (git-bash / scoop / choco)
|
|
74
|
+
("Vim", "vim"),
|
|
75
|
+
# Sublime Text
|
|
76
|
+
("Sublime Text", r"%PROGRAMFILES%\Sublime Text\subl.exe"),
|
|
77
|
+
("Sublime Text", r"%PROGRAMFILES%\Sublime Text 4\subl.exe"),
|
|
78
|
+
("Sublime Text", "subl"),
|
|
79
|
+
# Built-in last resort
|
|
80
|
+
("Notepad", "notepad"),
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
_MACOS_CANDIDATES: list[tuple[str, str | list[str]]] = [
|
|
84
|
+
("VS Code", "code"),
|
|
85
|
+
("Cursor", "cursor"),
|
|
86
|
+
("Neovim", "nvim"),
|
|
87
|
+
("Vim", "vim"),
|
|
88
|
+
("BBEdit", "/Applications/BBEdit.app/Contents/OS X Resources/bbedit"),
|
|
89
|
+
("BBEdit", "bbedit"),
|
|
90
|
+
("Nano", "nano"),
|
|
91
|
+
# TextEdit — open -e opens the file in TextEdit
|
|
92
|
+
("TextEdit", ["/usr/bin/open", "-e"]),
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
_LINUX_CANDIDATES: list[tuple[str, str | list[str]]] = [
|
|
96
|
+
("VS Code", "code"),
|
|
97
|
+
("Cursor", "cursor"),
|
|
98
|
+
("Neovim", "nvim"),
|
|
99
|
+
("Vim", "vim"),
|
|
100
|
+
("Nano", "nano"),
|
|
101
|
+
("Kate", "kate"),
|
|
102
|
+
("gedit", "gedit"),
|
|
103
|
+
("xed", "xed"),
|
|
104
|
+
("Mousepad", "mousepad"),
|
|
105
|
+
("Geany", "geany"),
|
|
106
|
+
("Micro", "micro"),
|
|
107
|
+
("Helix", "hx"),
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# ---------------------------------------------------------------------------
|
|
112
|
+
# Internal helpers
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _expand(path_str: str) -> str:
|
|
117
|
+
"""Expand environment variables in a path string (Windows-style %VAR%)."""
|
|
118
|
+
return os.path.expandvars(path_str)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _probe_command(cmd: str | list[str]) -> str | None:
|
|
122
|
+
"""Return the resolved path for *cmd* if it is runnable, else None."""
|
|
123
|
+
# Multi-token command (e.g. ["open", "-e"]) — probe the first token.
|
|
124
|
+
executable = cmd[0] if isinstance(cmd, list) else cmd
|
|
125
|
+
|
|
126
|
+
# Expand env vars in Windows-style paths (%PROGRAMFILES%\...)
|
|
127
|
+
expanded = _expand(executable)
|
|
128
|
+
if os.sep in expanded or "/" in expanded:
|
|
129
|
+
# Looks like an absolute/relative path — check if the file exists
|
|
130
|
+
p = Path(expanded)
|
|
131
|
+
if p.is_file() and os.access(p, os.X_OK):
|
|
132
|
+
return str(p)
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
# Plain command name — search PATH
|
|
136
|
+
found = shutil.which(executable)
|
|
137
|
+
return found if found else None
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _platform_candidates() -> list[tuple[str, str | list[str]]]:
|
|
141
|
+
system = platform.system()
|
|
142
|
+
if system == "Windows":
|
|
143
|
+
return _WINDOWS_CANDIDATES
|
|
144
|
+
if system == "Darwin":
|
|
145
|
+
return _MACOS_CANDIDATES
|
|
146
|
+
return _LINUX_CANDIDATES # Linux / BSD / WSL
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# ---------------------------------------------------------------------------
|
|
150
|
+
# Public API
|
|
151
|
+
# ---------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def list_detected_editors() -> list[EditorCandidate]:
|
|
155
|
+
"""Return all editor candidates that are runnable on this machine.
|
|
156
|
+
|
|
157
|
+
Each ``EditorCandidate`` is unique by *command* (the first token for
|
|
158
|
+
multi-token commands). Duplicates (e.g. multiple Notepad++ paths) are
|
|
159
|
+
deduplicated to the first match.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Ordered list of :class:`EditorCandidate`, best-first.
|
|
163
|
+
"""
|
|
164
|
+
seen_commands: set[str] = set()
|
|
165
|
+
result: list[EditorCandidate] = []
|
|
166
|
+
|
|
167
|
+
for display_name, cmd in _platform_candidates():
|
|
168
|
+
cmd_key = cmd[0] if isinstance(cmd, list) else cmd
|
|
169
|
+
if cmd_key in seen_commands:
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
resolved = _probe_command(cmd)
|
|
173
|
+
if resolved is None and isinstance(cmd, str):
|
|
174
|
+
# For plain command names that aren't found, skip
|
|
175
|
+
continue
|
|
176
|
+
if resolved is not None:
|
|
177
|
+
seen_commands.add(cmd_key)
|
|
178
|
+
result.append(
|
|
179
|
+
EditorCandidate(
|
|
180
|
+
name=display_name,
|
|
181
|
+
command=cmd_key,
|
|
182
|
+
path=resolved if resolved != cmd_key else None,
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return result
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def resolve_editor() -> str | None:
|
|
190
|
+
"""Return the editor command specsmith should use, or ``None`` if unresolvable.
|
|
191
|
+
|
|
192
|
+
Resolution order:
|
|
193
|
+
1. ``$EDITOR`` environment variable (user's explicit choice)
|
|
194
|
+
2. ``editor`` key in ``~/.specsmith/config.toml``
|
|
195
|
+
3. First auto-detected editor on this machine
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
The command string (e.g. ``"code"``, ``"notepad++"``, ``"nvim"``),
|
|
199
|
+
or ``None`` if nothing was found.
|
|
200
|
+
"""
|
|
201
|
+
# Priority 1: $EDITOR env var
|
|
202
|
+
env_editor = os.environ.get("EDITOR", "").strip()
|
|
203
|
+
if env_editor:
|
|
204
|
+
return env_editor
|
|
205
|
+
|
|
206
|
+
# Priority 2: ~/.specsmith/config.toml
|
|
207
|
+
config_editor = _read_config_editor()
|
|
208
|
+
if config_editor:
|
|
209
|
+
return config_editor
|
|
210
|
+
|
|
211
|
+
# Priority 3: auto-detect
|
|
212
|
+
candidates = list_detected_editors()
|
|
213
|
+
return candidates[0].command if candidates else None
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def set_editor_preference(command: str) -> Path:
|
|
217
|
+
"""Persist *command* as the preferred editor in ``~/.specsmith/config.toml``.
|
|
218
|
+
|
|
219
|
+
Creates the file and directory if they do not exist.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
command: The editor command to save (e.g. ``"code"``, ``"nvim"``).
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
The path of the written config file.
|
|
226
|
+
"""
|
|
227
|
+
config_path = _global_config_path()
|
|
228
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
229
|
+
|
|
230
|
+
# Read existing content (if any) and update/insert the editor key
|
|
231
|
+
existing = config_path.read_text(encoding="utf-8") if config_path.exists() else ""
|
|
232
|
+
lines = existing.splitlines()
|
|
233
|
+
|
|
234
|
+
# Find and replace an existing `editor = ...` line, or append
|
|
235
|
+
new_lines: list[str] = []
|
|
236
|
+
found = False
|
|
237
|
+
for line in lines:
|
|
238
|
+
stripped = line.strip()
|
|
239
|
+
if stripped.startswith("editor") and "=" in stripped:
|
|
240
|
+
new_lines.append(f'editor = "{command}"')
|
|
241
|
+
found = True
|
|
242
|
+
else:
|
|
243
|
+
new_lines.append(line)
|
|
244
|
+
if not found:
|
|
245
|
+
new_lines.append(f'editor = "{command}"')
|
|
246
|
+
|
|
247
|
+
config_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8")
|
|
248
|
+
return config_path
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
# ---------------------------------------------------------------------------
|
|
252
|
+
# Private helpers
|
|
253
|
+
# ---------------------------------------------------------------------------
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _global_config_path() -> Path:
|
|
257
|
+
"""Return ``~/.specsmith/config.toml``."""
|
|
258
|
+
return Path.home() / ".specsmith" / "config.toml"
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _read_config_editor() -> str | None:
|
|
262
|
+
"""Read the ``editor`` key from ``~/.specsmith/config.toml``."""
|
|
263
|
+
config_path = _global_config_path()
|
|
264
|
+
if not config_path.is_file():
|
|
265
|
+
return None
|
|
266
|
+
try:
|
|
267
|
+
# Minimal TOML parser for the editor key — avoids a tomllib dependency on 3.10
|
|
268
|
+
for line in config_path.read_text(encoding="utf-8").splitlines():
|
|
269
|
+
stripped = line.strip()
|
|
270
|
+
if stripped.startswith("editor") and "=" in stripped:
|
|
271
|
+
_, _, value = stripped.partition("=")
|
|
272
|
+
value = value.strip().strip('"').strip("'")
|
|
273
|
+
if value:
|
|
274
|
+
return value
|
|
275
|
+
except OSError:
|
|
276
|
+
pass
|
|
277
|
+
return None
|