specsmith 0.11.7.dev461__tar.gz → 0.11.7.dev469__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.7.dev461/src/specsmith.egg-info → specsmith-0.11.7.dev469}/PKG-INFO +38 -1
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/README.md +37 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/pyproject.toml +1 -1
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/auditor.py +46 -6
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/cli.py +21 -5
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/phase.py +2 -2
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/__init__.py +13 -4
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/governance.py +166 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/sync.py +12 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469/src/specsmith.egg-info}/PKG-INFO +38 -1
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith.egg-info/SOURCES.txt +1 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_auditor.py +105 -0
- specsmith-0.11.7.dev469/tests/test_req_358_359.py +101 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_skill_marketplace.py +49 -6
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/LICENSE +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/setup.cfg +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/belief.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/certainty.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/failure_graph.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/py.typed +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/recovery.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/session.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/stress_tester.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/epistemic/trace.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/__main__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/broker.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/chat_runner.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/cleanup.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/context_seed.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/core.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/dispatch/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/dispatch/_status.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/dispatch/dag.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/dispatch/events.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/dispatch/result.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/endpoints.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/events.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/execution_profiles.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/fallback.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/hf_leaderboard.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/hf_sync.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/indexer.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/llm_client.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/mcp.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/memory.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/model_intelligence.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/model_profiles.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/orchestrator.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/permissions.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/profiles.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/provider_registry.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/repl.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/router.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/rules.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/runner.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/safety.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/spawner.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/suggester.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/teams.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/tools.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/verifier.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/agent/voice.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/architect.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/auth.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/block_export.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/channel.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/ci_manager.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/commands/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/commands/intelligence.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/compliance/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/compliance/_compat.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/compliance/checker.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/compliance/evidence.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/compliance/regulations.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/compliance/reporter.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/compressor.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/config.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/console_utils.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/context_orchestrator.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/context_window.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/credit_analyzer.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/credits.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/base.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/citations.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/fpd.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/odp.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/patentsview.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/pfw.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/ppubs.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/datasources/ptab.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/differ.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/doctor.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/drive.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/editor.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/epistemic/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/epistemic/belief.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/epistemic/certainty.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/epistemic/failure_graph.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/epistemic/recovery.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/epistemic/stress_tester.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/esdb/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/esdb/bridge.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/eval/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/eval/builtins.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/eval/runner.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/executor.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/exporter.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/governance_logic.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/governance_store.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/governance_yaml.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/app.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/main_window.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/session_tab.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/theme.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/widgets/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/widgets/chat_view.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/widgets/input_bar.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/widgets/provider_bar.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/widgets/token_meter.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/widgets/tool_panel.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/widgets/update_checker.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/gui/worker.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/history_search.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/importer.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/instinct.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/agent_skill.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/aider.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/base.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/claude_code.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/codity.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/copilot.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/cursor.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/gemini.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/integrations/windsurf.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/issue_reporter.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/languages.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/ledger.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/mcp_generator.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/m002_agents_slim.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/m003_compliance_init.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/m006_session_governance.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/migrations/runner.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/ollama_cmds.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/patent.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/paths.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/plugins.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/profiles.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/rate_limits.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/releaser.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/requirements.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/requirements_parser.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/retrieval.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/safe_write.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/scaffolder.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/serve.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/session.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/session_init.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/session_store.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/cloud.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/corporate.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/cross_platform.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/devops.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/docs.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/embedded.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/hardware.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/mobile.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/productivity.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills/ssh.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/skills_builder.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/agents.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/contributing.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/license-MIT.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/community/security.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/editorconfig.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/gitattributes.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/gitignore.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/go/go.mod.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/go/main.go.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/roles.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/rules.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/governance/verification.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/js/package.json.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/ledger.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/python/cli.py.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/python/init.py.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/readme.md.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/rust/main.rs.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/tool_installer.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/toolrules.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/tools.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/trace.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/updater.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/upgrader.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/validator.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/vcs/__init__.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/vcs/base.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/vcs/bitbucket.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/vcs/github.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/vcs/gitlab.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/vcs_commands.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/wireframes.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith/workspace.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith.egg-info/dependency_links.txt +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith.egg-info/entry_points.txt +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith.egg-info/requires.txt +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/src/specsmith.egg-info/top_level.txt +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_CMD_001.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_agent_profiles.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_agent_run_feedback.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_agent_runner_ready.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_ai_client.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_ai_intelligence.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_channel.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_chat_diff_decision.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_chat_runner_openai_compat.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_chat_stdin_protocol.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_cli.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_cli_workflows_history_drive.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_compliance.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_compressor.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_dispatch.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_e2e_nexus.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_endpoints_cli.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_endpoints_store.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_epistemic.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_fallback_chain.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_importer.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_integrations.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_integrations_codity.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_intelligence.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_issue_reporter.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_mcp_client.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_new_modules.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_nexus.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_permissions.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_phase1_4_new.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_phase34_completion.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_rate_limits.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_req_248_262.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_scaffolder.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_skills_mcp.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_smoke.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_suggester.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_tools.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_validator.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_vcs.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/tests/test_warp_parity.py +0 -0
- {specsmith-0.11.7.dev461 → specsmith-0.11.7.dev469}/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.7.
|
|
3
|
+
Version: 0.11.7.dev469
|
|
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
|
|
@@ -957,6 +957,43 @@ See the `codity-ai-review` governance skill (`specsmith skill install codity-ai-
|
|
|
957
957
|
|
|
958
958
|
---
|
|
959
959
|
|
|
960
|
+
## Skills
|
|
961
|
+
|
|
962
|
+
specsmith ships **70+ built-in skills** across 11 domains that AI agents (Warp, Claude Code, Codex, Cursor) can install and use.
|
|
963
|
+
|
|
964
|
+
```bash
|
|
965
|
+
# List all available skills
|
|
966
|
+
specsmith skill list
|
|
967
|
+
|
|
968
|
+
# Search by keyword
|
|
969
|
+
specsmith skill search zephyr
|
|
970
|
+
|
|
971
|
+
# Install a skill into .agents/skills/
|
|
972
|
+
specsmith skill install specsmith
|
|
973
|
+
specsmith skill install specsmith-save
|
|
974
|
+
specsmith skill install specsmith-audit
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
Skills are installed as `.agents/skills/<slug>/SKILL.md` and are auto-discovered by any AI tool that scans `.agents/skills/`.
|
|
978
|
+
|
|
979
|
+
### Self-referential governance skills
|
|
980
|
+
|
|
981
|
+
Three skills document specsmith itself:
|
|
982
|
+
|
|
983
|
+
| Slug | Purpose |
|
|
984
|
+
|------|--------|
|
|
985
|
+
| `specsmith` | Master CLI reference — session workflow, commands, audit codes |
|
|
986
|
+
| `specsmith-save` | When and how to run `specsmith save` |
|
|
987
|
+
| `specsmith-audit` | Running audits and interpreting results |
|
|
988
|
+
|
|
989
|
+
### Remote reference (Warp Oz cloud agents)
|
|
990
|
+
|
|
991
|
+
```bash
|
|
992
|
+
oz agent run-cloud --skill "layer1labs/specsmith:specsmith-save" --prompt "save my work"
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
---
|
|
996
|
+
|
|
960
997
|
## The specsmith Bootstrap
|
|
961
998
|
|
|
962
999
|
specsmith governs itself — the specsmith repo is a specsmith-managed project. Run `specsmith audit`
|
|
@@ -885,6 +885,43 @@ See the `codity-ai-review` governance skill (`specsmith skill install codity-ai-
|
|
|
885
885
|
|
|
886
886
|
---
|
|
887
887
|
|
|
888
|
+
## Skills
|
|
889
|
+
|
|
890
|
+
specsmith ships **70+ built-in skills** across 11 domains that AI agents (Warp, Claude Code, Codex, Cursor) can install and use.
|
|
891
|
+
|
|
892
|
+
```bash
|
|
893
|
+
# List all available skills
|
|
894
|
+
specsmith skill list
|
|
895
|
+
|
|
896
|
+
# Search by keyword
|
|
897
|
+
specsmith skill search zephyr
|
|
898
|
+
|
|
899
|
+
# Install a skill into .agents/skills/
|
|
900
|
+
specsmith skill install specsmith
|
|
901
|
+
specsmith skill install specsmith-save
|
|
902
|
+
specsmith skill install specsmith-audit
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
Skills are installed as `.agents/skills/<slug>/SKILL.md` and are auto-discovered by any AI tool that scans `.agents/skills/`.
|
|
906
|
+
|
|
907
|
+
### Self-referential governance skills
|
|
908
|
+
|
|
909
|
+
Three skills document specsmith itself:
|
|
910
|
+
|
|
911
|
+
| Slug | Purpose |
|
|
912
|
+
|------|--------|
|
|
913
|
+
| `specsmith` | Master CLI reference — session workflow, commands, audit codes |
|
|
914
|
+
| `specsmith-save` | When and how to run `specsmith save` |
|
|
915
|
+
| `specsmith-audit` | Running audits and interpreting results |
|
|
916
|
+
|
|
917
|
+
### Remote reference (Warp Oz cloud agents)
|
|
918
|
+
|
|
919
|
+
```bash
|
|
920
|
+
oz agent run-cloud --skill "layer1labs/specsmith:specsmith-save" --prompt "save my work"
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
---
|
|
924
|
+
|
|
888
925
|
## The specsmith Bootstrap
|
|
889
926
|
|
|
890
927
|
specsmith governs itself — the specsmith repo is a specsmith-managed project. Run `specsmith audit`
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specsmith"
|
|
7
|
-
version = "0.11.7.
|
|
7
|
+
version = "0.11.7.dev469"
|
|
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"
|
|
@@ -23,6 +23,7 @@ class AuditResult:
|
|
|
23
23
|
passed: bool
|
|
24
24
|
message: str
|
|
25
25
|
fixable: bool = False
|
|
26
|
+
suppressed: bool = False
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
@dataclass
|
|
@@ -37,7 +38,7 @@ class AuditReport:
|
|
|
37
38
|
|
|
38
39
|
@property
|
|
39
40
|
def failed(self) -> int:
|
|
40
|
-
return sum(1 for r in self.results if not r.passed)
|
|
41
|
+
return sum(1 for r in self.results if not r.passed and not r.suppressed)
|
|
41
42
|
|
|
42
43
|
@property
|
|
43
44
|
def fixable(self) -> int:
|
|
@@ -47,6 +48,39 @@ class AuditReport:
|
|
|
47
48
|
def healthy(self) -> bool:
|
|
48
49
|
return self.failed == 0
|
|
49
50
|
|
|
51
|
+
@property
|
|
52
|
+
def suppressed_count(self) -> int:
|
|
53
|
+
return sum(1 for r in self.results if r.suppressed)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
# Suppression aliases (scaffold.yml accepted_warnings → AuditResult.name)
|
|
58
|
+
# ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
_SUPPRESSION_ALIASES: dict[str, str] = {
|
|
61
|
+
"scaffold_type_mismatch": "type-mismatch",
|
|
62
|
+
"ledger_line_threshold": "ledger-size",
|
|
63
|
+
"open_todo_count": "ledger-open-todos",
|
|
64
|
+
"ledger_size": "ledger-size",
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _apply_accepted_warnings(report: AuditReport, accepted: list[str]) -> None:
|
|
69
|
+
"""Mark audit results matching *accepted* warning names as suppressed.
|
|
70
|
+
|
|
71
|
+
Each entry in *accepted* is either a key in ``_SUPPRESSION_ALIASES`` or a
|
|
72
|
+
direct ``AuditResult.name`` (exact match or prefix match up to ``:``).
|
|
73
|
+
Matched results are set to ``suppressed=True`` and ``passed=True`` so they
|
|
74
|
+
no longer count as failures.
|
|
75
|
+
"""
|
|
76
|
+
resolved: list[str] = [_SUPPRESSION_ALIASES.get(a, a) for a in accepted]
|
|
77
|
+
for result in report.results:
|
|
78
|
+
for name in resolved:
|
|
79
|
+
if result.name == name or result.name.startswith(name + ":"):
|
|
80
|
+
result.suppressed = True
|
|
81
|
+
result.passed = True
|
|
82
|
+
break
|
|
83
|
+
|
|
50
84
|
|
|
51
85
|
# ---------------------------------------------------------------------------
|
|
52
86
|
# Governance file existence checks
|
|
@@ -386,10 +420,7 @@ def check_ledger_health(root: Path) -> list[AuditResult]:
|
|
|
386
420
|
|
|
387
421
|
# Size check — uses configurable threshold (#145)
|
|
388
422
|
threshold = _get_ledger_threshold(root)
|
|
389
|
-
|
|
390
|
-
raw = _read_scaffold_raw(root)
|
|
391
|
-
suppressed = "ledger_size" in (raw.get("audit_suppressions") or [])
|
|
392
|
-
if not suppressed and line_count > threshold:
|
|
423
|
+
if line_count > threshold:
|
|
393
424
|
results.append(
|
|
394
425
|
AuditResult(
|
|
395
426
|
name="ledger-size",
|
|
@@ -1171,6 +1202,15 @@ def run_audit(root: Path) -> AuditReport:
|
|
|
1171
1202
|
report.results.extend(check_industrial_artifacts(root))
|
|
1172
1203
|
report.results.extend(check_derived_artifacts(root))
|
|
1173
1204
|
report.results.extend(check_cross_repo_dependencies(root))
|
|
1205
|
+
|
|
1206
|
+
# Apply accepted_warnings / audit_suppressions from scaffold.yml (REQ-357)
|
|
1207
|
+
raw = _read_scaffold_raw(root)
|
|
1208
|
+
_accepted: list[str] = list(raw.get("accepted_warnings") or [])
|
|
1209
|
+
# backward-compat: audit_suppressions list (pre-#188 ledger_size suppression)
|
|
1210
|
+
_old_suppressed: list[str] = list(raw.get("audit_suppressions") or [])
|
|
1211
|
+
_accepted = _accepted + _old_suppressed
|
|
1212
|
+
if _accepted:
|
|
1213
|
+
_apply_accepted_warnings(report, _accepted)
|
|
1174
1214
|
return report
|
|
1175
1215
|
|
|
1176
1216
|
|
|
@@ -1182,7 +1222,7 @@ def run_auto_fix(root: Path, report: AuditReport) -> list[str]:
|
|
|
1182
1222
|
fixed: list[str] = []
|
|
1183
1223
|
|
|
1184
1224
|
for result in report.results:
|
|
1185
|
-
if result.passed:
|
|
1225
|
+
if result.passed or result.suppressed:
|
|
1186
1226
|
continue
|
|
1187
1227
|
|
|
1188
1228
|
# Fix missing required files with minimal stubs
|
|
@@ -441,8 +441,14 @@ def audit(fix: bool, project_dir: str) -> None:
|
|
|
441
441
|
report = run_audit(root)
|
|
442
442
|
|
|
443
443
|
for r in report.results:
|
|
444
|
-
|
|
445
|
-
|
|
444
|
+
if r.suppressed:
|
|
445
|
+
icon = "[dim]~[/dim]"
|
|
446
|
+
elif r.passed:
|
|
447
|
+
icon = "[green]✓[/green]"
|
|
448
|
+
else:
|
|
449
|
+
icon = "[red]✗[/red]"
|
|
450
|
+
msg = r.message + " [dim](accepted)[/dim]" if r.suppressed else r.message
|
|
451
|
+
console.print(f" {icon} {msg}")
|
|
446
452
|
|
|
447
453
|
console.print()
|
|
448
454
|
if report.healthy:
|
|
@@ -2350,7 +2356,7 @@ def release(version: str, project_dir: str) -> None:
|
|
|
2350
2356
|
f"\n[bold]Next steps:[/bold]\n"
|
|
2351
2357
|
f" 1. Update CHANGELOG.md with [{version}] section\n"
|
|
2352
2358
|
f" 2. git add -A && git commit -m 'release: v{version}'\n"
|
|
2353
|
-
f" 3. git checkout main && git merge develop\n"
|
|
2359
|
+
f" 3. git checkout main && git merge develop --no-edit\n"
|
|
2354
2360
|
f" 4. git tag -a v{version} -m 'v{version}'\n"
|
|
2355
2361
|
f" 5. git push origin main develop --tags"
|
|
2356
2362
|
)
|
|
@@ -8524,9 +8530,19 @@ def skill_list(project_dir: str, as_json: bool) -> None:
|
|
|
8524
8530
|
from specsmith import skills as _skills
|
|
8525
8531
|
|
|
8526
8532
|
root = Path(project_dir).resolve()
|
|
8527
|
-
|
|
8533
|
+
installed_paths = _skills.installed_skills(root)
|
|
8534
|
+
# Build identifier list: slug (subdir) or filename (flat legacy)
|
|
8535
|
+
installed: list[str] = []
|
|
8536
|
+
installed_slugs: set[str] = set()
|
|
8537
|
+
for p in installed_paths:
|
|
8538
|
+
if p.name == "SKILL.md": # subdir format: <slug>/SKILL.md
|
|
8539
|
+
installed.append(p.parent.name)
|
|
8540
|
+
installed_slugs.add(p.parent.name)
|
|
8541
|
+
else: # legacy flat format: <slug>.md
|
|
8542
|
+
installed.append(p.name)
|
|
8543
|
+
installed_slugs.add(p.stem)
|
|
8528
8544
|
catalog = [
|
|
8529
|
-
{"slug": entry.slug, "name": entry.name, "installed":
|
|
8545
|
+
{"slug": entry.slug, "name": entry.name, "installed": entry.slug in installed_slugs}
|
|
8530
8546
|
for entry in _skills.CATALOG
|
|
8531
8547
|
]
|
|
8532
8548
|
if as_json:
|
|
@@ -77,8 +77,8 @@ def _req_count(min_count: int) -> Callable[[Path], bool]:
|
|
|
77
77
|
if p.exists():
|
|
78
78
|
try:
|
|
79
79
|
text = p.read_text(encoding="utf-8", errors="ignore")
|
|
80
|
-
# Support
|
|
81
|
-
count = len(re.findall(r"
|
|
80
|
+
# Support H2/H3 headings (## REQ-NNN, ### REQ-NNN, ## REQ-BE-001) (REQ-359)
|
|
81
|
+
count = len(re.findall(r"^#{2,3}\s+REQ-", text, re.MULTILINE))
|
|
82
82
|
if count == 0:
|
|
83
83
|
count = len(re.findall(r"- \*\*ID:\*\* REQ-", text))
|
|
84
84
|
if count == 0:
|
|
@@ -207,15 +207,21 @@ def by_project_type(project_type: str) -> list[SkillEntry]:
|
|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
def installed_skills(project_dir: Path) -> list[Path]:
|
|
210
|
-
"""Return
|
|
210
|
+
"""Return installed skill files under ``.agents/skills/`` (both flat and subdir formats)."""
|
|
211
211
|
base = project_dir / ".agents" / "skills"
|
|
212
212
|
if not base.is_dir():
|
|
213
213
|
return []
|
|
214
|
-
|
|
214
|
+
paths: list[Path] = []
|
|
215
|
+
for item in sorted(base.iterdir()):
|
|
216
|
+
if item.is_file() and item.suffix == ".md": # legacy flat format
|
|
217
|
+
paths.append(item)
|
|
218
|
+
elif item.is_dir() and (item / "SKILL.md").exists(): # subdir format
|
|
219
|
+
paths.append(item / "SKILL.md")
|
|
220
|
+
return sorted(paths)
|
|
215
221
|
|
|
216
222
|
|
|
217
223
|
def install(slug: str, project_dir: Path, *, force: bool = False) -> Path:
|
|
218
|
-
"""Copy skill *slug* into ``<project_dir>/.agents/skills/<slug
|
|
224
|
+
"""Copy skill *slug* into ``<project_dir>/.agents/skills/<slug>/SKILL.md``.
|
|
219
225
|
|
|
220
226
|
Raises
|
|
221
227
|
------
|
|
@@ -229,7 +235,10 @@ def install(slug: str, project_dir: Path, *, force: bool = False) -> Path:
|
|
|
229
235
|
raise KeyError(f"Unknown skill: {slug!r}")
|
|
230
236
|
base = project_dir / ".agents" / "skills"
|
|
231
237
|
base.mkdir(parents=True, exist_ok=True)
|
|
232
|
-
|
|
238
|
+
# Subdirectory format: <slug>/SKILL.md (REQ-360)
|
|
239
|
+
skill_dir = base / slug
|
|
240
|
+
skill_dir.mkdir(exist_ok=True)
|
|
241
|
+
target = skill_dir / "SKILL.md"
|
|
233
242
|
if target.exists() and not force:
|
|
234
243
|
raise FileExistsError(f"Already installed: {target}. Pass force=True to overwrite.")
|
|
235
244
|
target.write_text(entry.body, encoding="utf-8")
|
|
@@ -293,6 +293,172 @@ print("Rust backend:", RUST_BACKEND)
|
|
|
293
293
|
"""
|
|
294
294
|
),
|
|
295
295
|
),
|
|
296
|
+
SkillEntry(
|
|
297
|
+
slug="specsmith",
|
|
298
|
+
name="Specsmith — master governance CLI reference",
|
|
299
|
+
description=(
|
|
300
|
+
"Master reference for the specsmith AEE governance tool — key concepts, "
|
|
301
|
+
"common commands, session workflow, phase advancement, and audit codes. "
|
|
302
|
+
"Use whenever working in a specsmith-governed project."
|
|
303
|
+
),
|
|
304
|
+
domain=SkillDomain.GOVERNANCE,
|
|
305
|
+
tags=["specsmith", "governance", "aee", "cli", "session", "audit", "phase", "ledger"],
|
|
306
|
+
prerequisites=["specsmith"],
|
|
307
|
+
body="""\
|
|
308
|
+
# Specsmith — Master Governance CLI Reference
|
|
309
|
+
|
|
310
|
+
specsmith is the Applied Epistemic Engineering (AEE) toolkit for AI-assisted
|
|
311
|
+
development. It governs projects through a 7-phase lifecycle and enforces
|
|
312
|
+
22 hard rules (H1–H22) via preflight gates, audits, and cryptographic trace
|
|
313
|
+
vaults.
|
|
314
|
+
|
|
315
|
+
## Key Concepts
|
|
316
|
+
- **AEE Phase** — inception → architecture → requirements → test_spec →
|
|
317
|
+
implementation → verification → release. `specsmith phase` shows the
|
|
318
|
+
current phase and readiness percentage.
|
|
319
|
+
- **Preflight Gate** — every proposed change must pass
|
|
320
|
+
`specsmith preflight "<intent>" --json` before execution.
|
|
321
|
+
- **Work Item** — a scoped unit of work (`WI-<hash>`) assigned by preflight.
|
|
322
|
+
- **Governance Anchor** — `specsmith checkpoint` emits a timestamped snapshot
|
|
323
|
+
of phase, health, and active work items.
|
|
324
|
+
- **ESDB** — EpiStemic State Database (ChronoMemory WAL) stores beliefs,
|
|
325
|
+
decisions, and trace seals.
|
|
326
|
+
|
|
327
|
+
## Common Commands
|
|
328
|
+
```bash
|
|
329
|
+
specsmith audit # governance health (28 checks)
|
|
330
|
+
specsmith sync # YAML → JSON → Markdown sync
|
|
331
|
+
specsmith validate --strict # schema validation
|
|
332
|
+
specsmith preflight "..." # preflight gate
|
|
333
|
+
specsmith checkpoint # emit GOVERNANCE ANCHOR
|
|
334
|
+
specsmith save # ESDB backup + commit + push
|
|
335
|
+
specsmith phase # show current phase + readiness
|
|
336
|
+
specsmith phase next # advance phase (checks prerequisites)
|
|
337
|
+
specsmith kill-session # terminate all agent processes
|
|
338
|
+
specsmith ledger add "msg" # append to LEDGER.md
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Session Workflow
|
|
342
|
+
1. `specsmith audit && specsmith sync && specsmith checkpoint`
|
|
343
|
+
2. `specsmith preflight "<describe change>" --json`
|
|
344
|
+
3. Execute work (only if decision == accepted)
|
|
345
|
+
4. Every 8-10 turns: `specsmith checkpoint` (output verbatim)
|
|
346
|
+
5. `specsmith save && specsmith kill-session`
|
|
347
|
+
|
|
348
|
+
## Audit Codes
|
|
349
|
+
- 28 checks across structure, REQ↔TEST coverage, governance size,
|
|
350
|
+
tool config, phase readiness, and supplementary rules.
|
|
351
|
+
- `specsmith audit --fix` auto-repairs missing files and CI configs.
|
|
352
|
+
|
|
353
|
+
## Phase Advancement
|
|
354
|
+
- `specsmith phase next` checks prerequisites before advancing.
|
|
355
|
+
- `specsmith phase set <phase>` jumps (with `--force` to skip checks).
|
|
356
|
+
- Phase stored as `aee_phase` in `scaffold.yml`.
|
|
357
|
+
""",
|
|
358
|
+
),
|
|
359
|
+
SkillEntry(
|
|
360
|
+
slug="specsmith-audit",
|
|
361
|
+
name="Specsmith Audit — drift detection and governance health",
|
|
362
|
+
description=(
|
|
363
|
+
"Run specsmith audit to check for governance drift between requirements, "
|
|
364
|
+
"tests, and architecture. Required before advancing an AEE phase."
|
|
365
|
+
),
|
|
366
|
+
domain=SkillDomain.GOVERNANCE,
|
|
367
|
+
tags=["specsmith", "audit", "drift", "health", "governance", "aee", "requirements"],
|
|
368
|
+
prerequisites=["specsmith"],
|
|
369
|
+
body="""\
|
|
370
|
+
# Specsmith Audit — Drift Detection and Governance Health
|
|
371
|
+
|
|
372
|
+
## When to Run
|
|
373
|
+
- At the start of every session (part of bootstrap)
|
|
374
|
+
- Before advancing an AEE phase (`specsmith phase next`)
|
|
375
|
+
- After significant code or requirements changes
|
|
376
|
+
- When drift is suspected (stale coverage, missing tests)
|
|
377
|
+
|
|
378
|
+
## Command
|
|
379
|
+
```bash
|
|
380
|
+
specsmith audit # full 28-check governance audit
|
|
381
|
+
specsmith audit --fix # auto-repair missing files
|
|
382
|
+
specsmith audit --project-dir . # explicit project root
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## What It Checks (28 checks)
|
|
386
|
+
1. Governance file structure (.specsmith/, docs/, AGENTS.md)
|
|
387
|
+
2. REQ↔TEST bidirectional coverage (no orphan tests, no untested REQs)
|
|
388
|
+
3. Governance file size thresholds
|
|
389
|
+
4. CI tool configuration matches project type
|
|
390
|
+
5. Phase readiness prerequisites
|
|
391
|
+
6. Supplementary rules referenced in AGENTS.md
|
|
392
|
+
7. Duplicate governance files (root vs docs/ canonical)
|
|
393
|
+
8. YAML↔JSON↔Markdown sync state
|
|
394
|
+
|
|
395
|
+
## Interpreting Results
|
|
396
|
+
- **28/28 checks passed** — governance is healthy
|
|
397
|
+
- **Failures** — surface to user before starting work
|
|
398
|
+
- **Warnings** — non-blocking but should be addressed
|
|
399
|
+
|
|
400
|
+
## Suppressing Warnings
|
|
401
|
+
In `scaffold.yml`:
|
|
402
|
+
```yaml
|
|
403
|
+
accepted_warnings:
|
|
404
|
+
- <alias> # renders as ~ <check> (accepted), excluded from failure count
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Integration with Phase Advancement
|
|
408
|
+
`specsmith phase next` runs audit internally. All checks must pass
|
|
409
|
+
(or be accepted) before the phase advances.
|
|
410
|
+
""",
|
|
411
|
+
),
|
|
412
|
+
SkillEntry(
|
|
413
|
+
slug="specsmith-save",
|
|
414
|
+
name="Specsmith Save — governance-aware save workflow",
|
|
415
|
+
description=(
|
|
416
|
+
"Run specsmith save to commit and push all current changes with governance "
|
|
417
|
+
"state backup. Use at the end of any work session or after completing a feature/fix."
|
|
418
|
+
),
|
|
419
|
+
domain=SkillDomain.GOVERNANCE,
|
|
420
|
+
tags=["specsmith", "save", "commit", "push", "esdb", "backup", "governance"],
|
|
421
|
+
prerequisites=["specsmith"],
|
|
422
|
+
body="""\
|
|
423
|
+
# Specsmith Save — Governance-Aware Save Workflow
|
|
424
|
+
|
|
425
|
+
## When to Use
|
|
426
|
+
- At the end of every work session
|
|
427
|
+
- After completing a feature or fix
|
|
428
|
+
- Before switching branches or contexts
|
|
429
|
+
- Never end a session with uncommitted governance changes
|
|
430
|
+
|
|
431
|
+
## Command
|
|
432
|
+
```bash
|
|
433
|
+
specsmith save # ESDB backup + commit + push
|
|
434
|
+
specsmith save --project-dir . # explicit project root
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## What It Does (in order)
|
|
438
|
+
1. Creates a timestamped ESDB backup (.specsmith/backups/)
|
|
439
|
+
2. Runs `git add -A` to stage all changes
|
|
440
|
+
3. Commits with a governance-stamped message
|
|
441
|
+
4. Pushes to the current remote branch
|
|
442
|
+
|
|
443
|
+
## Prerequisites
|
|
444
|
+
- All governance changes must be consistent (run `specsmith audit` first
|
|
445
|
+
if unsure)
|
|
446
|
+
- A git remote must be configured
|
|
447
|
+
- Working tree should have changes to commit
|
|
448
|
+
|
|
449
|
+
## Session End Protocol
|
|
450
|
+
```bash
|
|
451
|
+
specsmith save --project-dir . # ESDB backup + commit + push
|
|
452
|
+
specsmith kill-session # stop governance-serve and tracked processes
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## ESDB Backup Details
|
|
456
|
+
- Backups are written to `.specsmith/backups/`
|
|
457
|
+
- Filename format: `backup-YYYY-MM-DDTHH-MM-SS.json`
|
|
458
|
+
- Contains requirements.json and testcases.json snapshots
|
|
459
|
+
- Use `specsmith esdb rollback --steps N` to restore from backup
|
|
460
|
+
""",
|
|
461
|
+
),
|
|
296
462
|
SkillEntry(
|
|
297
463
|
slug="specsmith-session-governance",
|
|
298
464
|
name="Specsmith Session Governance — drift prevention, heartbeat, preflight gate",
|
|
@@ -240,6 +240,18 @@ def run_sync(root: Path, *, dry_run: bool = False) -> SyncResult:
|
|
|
240
240
|
new_reqs = load_yaml_requirements(root)
|
|
241
241
|
new_tests = load_yaml_tests(root)
|
|
242
242
|
|
|
243
|
+
# REQ-358: If YAML mode has no YAML files but REQUIREMENTS.md has content,
|
|
244
|
+
# fall back to Markdown parsing rather than silently producing an empty state.
|
|
245
|
+
if not new_reqs and reqs_md_path.exists():
|
|
246
|
+
_md_text = reqs_md_path.read_text(encoding="utf-8")
|
|
247
|
+
import re as _re
|
|
248
|
+
|
|
249
|
+
if len(_re.findall(r"REQ-[A-Z0-9-]+", _md_text)) >= 5:
|
|
250
|
+
new_reqs = parse_requirements_md(_md_text)
|
|
251
|
+
|
|
252
|
+
if not new_tests and tests_md_path.exists():
|
|
253
|
+
new_tests = parse_tests_md(tests_md_path.read_text(encoding="utf-8"))
|
|
254
|
+
|
|
243
255
|
# Normalise to the same schema that the Markdown path produces
|
|
244
256
|
# Build req_id → [test_ids] map from the loaded tests so requirements.json
|
|
245
257
|
# includes test_ids for audit coverage checks (#147).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specsmith
|
|
3
|
-
Version: 0.11.7.
|
|
3
|
+
Version: 0.11.7.dev469
|
|
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
|
|
@@ -957,6 +957,43 @@ See the `codity-ai-review` governance skill (`specsmith skill install codity-ai-
|
|
|
957
957
|
|
|
958
958
|
---
|
|
959
959
|
|
|
960
|
+
## Skills
|
|
961
|
+
|
|
962
|
+
specsmith ships **70+ built-in skills** across 11 domains that AI agents (Warp, Claude Code, Codex, Cursor) can install and use.
|
|
963
|
+
|
|
964
|
+
```bash
|
|
965
|
+
# List all available skills
|
|
966
|
+
specsmith skill list
|
|
967
|
+
|
|
968
|
+
# Search by keyword
|
|
969
|
+
specsmith skill search zephyr
|
|
970
|
+
|
|
971
|
+
# Install a skill into .agents/skills/
|
|
972
|
+
specsmith skill install specsmith
|
|
973
|
+
specsmith skill install specsmith-save
|
|
974
|
+
specsmith skill install specsmith-audit
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
Skills are installed as `.agents/skills/<slug>/SKILL.md` and are auto-discovered by any AI tool that scans `.agents/skills/`.
|
|
978
|
+
|
|
979
|
+
### Self-referential governance skills
|
|
980
|
+
|
|
981
|
+
Three skills document specsmith itself:
|
|
982
|
+
|
|
983
|
+
| Slug | Purpose |
|
|
984
|
+
|------|--------|
|
|
985
|
+
| `specsmith` | Master CLI reference — session workflow, commands, audit codes |
|
|
986
|
+
| `specsmith-save` | When and how to run `specsmith save` |
|
|
987
|
+
| `specsmith-audit` | Running audits and interpreting results |
|
|
988
|
+
|
|
989
|
+
### Remote reference (Warp Oz cloud agents)
|
|
990
|
+
|
|
991
|
+
```bash
|
|
992
|
+
oz agent run-cloud --skill "layer1labs/specsmith:specsmith-save" --prompt "save my work"
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
---
|
|
996
|
+
|
|
960
997
|
## The specsmith Bootstrap
|
|
961
998
|
|
|
962
999
|
specsmith governs itself — the specsmith repo is a specsmith-managed project. Run `specsmith audit`
|
|
@@ -199,3 +199,108 @@ class TestReqTraceLetterSuffixRegression:
|
|
|
199
199
|
assert "TEST-NN-002a" in ids
|
|
200
200
|
assert "TEST-NN-002b" in ids
|
|
201
201
|
assert "TEST-NN-002" not in ids # must not be truncated
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# ---------------------------------------------------------------------------
|
|
205
|
+
# REQ-357: accepted_warnings suppression
|
|
206
|
+
# ---------------------------------------------------------------------------
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class TestAcceptedWarningsSuppression:
|
|
210
|
+
"""Tests for REQ-357 — accepted_warnings suppression in auditor."""
|
|
211
|
+
|
|
212
|
+
def test_accepted_warnings_suppresses_type_mismatch(self, tmp_path: Path) -> None:
|
|
213
|
+
"""scaffold_type_mismatch alias should suppress the type-mismatch check."""
|
|
214
|
+
# Set up a minimal project with a type that will mismatch detection
|
|
215
|
+
(tmp_path / "AGENTS.md").write_text("# AGENTS\nShort.\n", encoding="utf-8")
|
|
216
|
+
(tmp_path / "LEDGER.md").write_text("# Ledger\nDone.\n", encoding="utf-8")
|
|
217
|
+
docs = tmp_path / "docs"
|
|
218
|
+
docs.mkdir()
|
|
219
|
+
(docs / "TESTS.md").write_text("# Tests\n", encoding="utf-8")
|
|
220
|
+
# Use a type that differs from what detect_project will infer.
|
|
221
|
+
# "backend-frontend" is unlikely to match a near-empty tmp project.
|
|
222
|
+
(tmp_path / "scaffold.yml").write_text(
|
|
223
|
+
"name: test\n"
|
|
224
|
+
"type: backend-frontend\n"
|
|
225
|
+
"spec_version: 0.10.1\n"
|
|
226
|
+
"vcs_platform: github\n"
|
|
227
|
+
"accepted_warnings:\n"
|
|
228
|
+
" - scaffold_type_mismatch\n",
|
|
229
|
+
encoding="utf-8",
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
report = run_audit(tmp_path)
|
|
233
|
+
|
|
234
|
+
# Find the type-mismatch result
|
|
235
|
+
tm_results = [r for r in report.results if r.name == "type-mismatch"]
|
|
236
|
+
if tm_results:
|
|
237
|
+
assert tm_results[0].suppressed is True
|
|
238
|
+
assert tm_results[0].passed is True
|
|
239
|
+
# The suppressed result must not count as a failure
|
|
240
|
+
type_mismatch_failures = [
|
|
241
|
+
r for r in report.results if r.name == "type-mismatch" and not r.passed
|
|
242
|
+
]
|
|
243
|
+
assert len(type_mismatch_failures) == 0
|
|
244
|
+
|
|
245
|
+
def test_ledger_line_threshold_suppresses_ledger_size(self, tmp_path: Path) -> None:
|
|
246
|
+
"""ledger_line_threshold alias should suppress ledger-size check."""
|
|
247
|
+
(tmp_path / "AGENTS.md").write_text("# AGENTS\nShort.\n", encoding="utf-8")
|
|
248
|
+
big_ledger = "# Ledger\n" + "\n".join(f"Line {i}" for i in range(600))
|
|
249
|
+
(tmp_path / "LEDGER.md").write_text(big_ledger, encoding="utf-8")
|
|
250
|
+
(tmp_path / "scaffold.yml").write_text(
|
|
251
|
+
"name: test\n"
|
|
252
|
+
"type: cli-python\n"
|
|
253
|
+
"spec_version: 0.10.1\n"
|
|
254
|
+
"vcs_platform: github\n"
|
|
255
|
+
"accepted_warnings:\n"
|
|
256
|
+
" - ledger_line_threshold\n",
|
|
257
|
+
encoding="utf-8",
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
report = run_audit(tmp_path)
|
|
261
|
+
|
|
262
|
+
size_results = [r for r in report.results if r.name == "ledger-size"]
|
|
263
|
+
assert len(size_results) == 1
|
|
264
|
+
assert size_results[0].suppressed is True
|
|
265
|
+
assert size_results[0].passed is True
|
|
266
|
+
# Should not count toward failures
|
|
267
|
+
assert all(r.passed or r.name != "ledger-size" for r in report.results)
|
|
268
|
+
|
|
269
|
+
def test_audit_suppressions_backward_compat(self, tmp_path: Path) -> None:
|
|
270
|
+
"""Old audit_suppressions: [ledger_size] field should still suppress ledger-size."""
|
|
271
|
+
(tmp_path / "AGENTS.md").write_text("# AGENTS\nShort.\n", encoding="utf-8")
|
|
272
|
+
big_ledger = "# Ledger\n" + "\n".join(f"Line {i}" for i in range(600))
|
|
273
|
+
(tmp_path / "LEDGER.md").write_text(big_ledger, encoding="utf-8")
|
|
274
|
+
(tmp_path / "scaffold.yml").write_text(
|
|
275
|
+
"name: test\n"
|
|
276
|
+
"type: cli-python\n"
|
|
277
|
+
"spec_version: 0.10.1\n"
|
|
278
|
+
"vcs_platform: github\n"
|
|
279
|
+
"audit_suppressions:\n"
|
|
280
|
+
" - ledger_size\n",
|
|
281
|
+
encoding="utf-8",
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
report = run_audit(tmp_path)
|
|
285
|
+
|
|
286
|
+
size_results = [r for r in report.results if r.name == "ledger-size"]
|
|
287
|
+
assert len(size_results) == 1
|
|
288
|
+
assert size_results[0].suppressed is True
|
|
289
|
+
assert size_results[0].passed is True
|
|
290
|
+
|
|
291
|
+
def test_suppressed_count_property(self, tmp_path: Path) -> None:
|
|
292
|
+
"""AuditReport.suppressed_count should reflect the number of suppressed results."""
|
|
293
|
+
from specsmith.auditor import AuditReport, AuditResult, _apply_accepted_warnings
|
|
294
|
+
|
|
295
|
+
report = AuditReport(
|
|
296
|
+
results=[
|
|
297
|
+
AuditResult(name="ledger-size", passed=False, message="too big", fixable=True),
|
|
298
|
+
AuditResult(name="type-mismatch", passed=False, message="mismatch"),
|
|
299
|
+
AuditResult(name="other-check", passed=True, message="ok"),
|
|
300
|
+
]
|
|
301
|
+
)
|
|
302
|
+
_apply_accepted_warnings(report, ["ledger_line_threshold", "scaffold_type_mismatch"])
|
|
303
|
+
|
|
304
|
+
assert report.suppressed_count == 2
|
|
305
|
+
assert report.failed == 0
|
|
306
|
+
assert report.healthy is True
|