specsmith 0.17.1.dev667__tar.gz → 0.17.1.dev684__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.17.1.dev667/src/specsmith.egg-info → specsmith-0.17.1.dev684}/PKG-INFO +1 -1
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/pyproject.toml +1 -1
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/context_seed.py +134 -3
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/runner.py +42 -1
- specsmith-0.17.1.dev684/src/specsmith/agent/token_pricing.py +191 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/auditor.py +2 -1
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/cli.py +292 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/_compat.py +89 -44
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/context_orchestrator.py +75 -4
- specsmith-0.17.1.dev684/src/specsmith/efficiency.py +293 -0
- specsmith-0.17.1.dev684/src/specsmith/esdb_sweep.py +225 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb_writer.py +202 -2
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/ledger.py +17 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/__init__.py +4 -0
- specsmith-0.17.1.dev684/src/specsmith/migrations/m009_esdb_first.py +257 -0
- specsmith-0.17.1.dev684/src/specsmith/migrations/m010_post_esdb_cleanup.py +241 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/project_metrics.py +7 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/serve.py +11 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/agents.md.j2 +33 -2
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/trace.py +7 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs_commands.py +25 -1
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684/src/specsmith.egg-info}/PKG-INFO +1 -1
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/SOURCES.txt +13 -0
- specsmith-0.17.1.dev684/tests/test_benchmark_harness.py +688 -0
- specsmith-0.17.1.dev684/tests/test_dual_write.py +268 -0
- specsmith-0.17.1.dev684/tests/test_efficiency.py +246 -0
- specsmith-0.17.1.dev684/tests/test_esdb_sweep.py +267 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_nexus.py +8 -3
- specsmith-0.17.1.dev684/tests/test_parallel_agents.py +511 -0
- specsmith-0.17.1.dev684/tests/test_repl_extended.py +391 -0
- specsmith-0.17.1.dev684/tests/test_resume_command.py +188 -0
- specsmith-0.17.1.dev684/tests/test_token_cost.py +319 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/LICENSE +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/README.md +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/setup.cfg +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/belief.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/certainty.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/failure_graph.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/py.typed +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/recovery.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/session.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/stress_tester.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/trace.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/__main__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/broker.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/chat_runner.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/cleanup.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/core.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/_status.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/dag.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/events.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/result.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/endpoints.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/events.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/execution_profiles.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/fallback.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/hf_leaderboard.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/hf_sync.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/indexer.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/llm_client.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/mcp.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/memory.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/model_intelligence.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/model_profiles.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/model_router.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/orchestrator.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/permissions.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/profiles.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/provider_registry.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/repl.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/router.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/rules.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/safety.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/spawner.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/suggester.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/teams.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/tools.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/verifier.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/voice.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/approvals.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/architect.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/auth.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/block_export.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/channel.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/ci_manager.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/intelligence.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/issues_policy.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/reporting.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/checker.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/evidence.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/regulations.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/reporter.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compressor.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/config.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/console_utils.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/context_window.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/credit_analyzer.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/credits.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/dashboard.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/base.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/citations.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/fpd.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/odp.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/patentsview.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/pfw.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/ppubs.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/ptab.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/differ.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/doctor.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/drive.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/editor.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/belief.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/certainty.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/failure_graph.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/recovery.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/stress_tester.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/_license.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/bridge.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/sqlite_store.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/eval/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/eval/builtins.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/eval/runner.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/executor.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/exporter.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governance_logic.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governance_store.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governance_yaml.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governed_pr.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/app.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/main_window.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/session_tab.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/theme.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/chat_view.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/input_bar.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/provider_bar.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/token_meter.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/tool_panel.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/update_checker.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/worker.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/history_search.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/importer.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/instinct.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/agent_skill.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/aider.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/base.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/claude_code.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/codity.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/copilot.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/cursor.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/gemini.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/windsurf.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/issue_reporter.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/languages.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/local_model.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/mcp_generator.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/mcp_server.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m002_agents_slim.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m003_compliance_init.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m006_session_governance.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m007_yaml_first.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m008_esdb_full_coverage.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/runner.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/ollama_cmds.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/patent.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/paths.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/phase.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/plugins.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/policy.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/profiles.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/quality_report.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/rate_limits.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/recover.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/releaser.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/requirements.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/requirements_parser.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/retrieval.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/risk.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/safe_write.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/scaffolder.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/session.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/session_init.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/session_store.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/ai_agents.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/cloud.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/corporate.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/cross_platform.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/data_engineering.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/devops.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/docs.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/embedded.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/governance.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/hardware.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/mobile.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/platform_engineering.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/productivity.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/software_engineering.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/specsmith_skills.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/ssh.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/web_backend.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills_builder.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/sync.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/contributing.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/license-MIT.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/security.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/editorconfig.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/gitattributes.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/gitignore.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/go/go.mod.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/go/main.go.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/roles.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/rules.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/verification.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/js/package.json.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/ledger.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/python/cli.py.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/python/init.py.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/readme.md.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/rust/main.rs.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/tool_installer.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/toolrules.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/tools.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/transcripts.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/updater.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/upgrader.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/validator.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/__init__.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/base.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/bitbucket.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/github.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/gitlab.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/wi_store.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/wireframes.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/workspace.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/dependency_links.txt +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/entry_points.txt +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/requires.txt +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/top_level.txt +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_CMD_001.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_agent_profiles.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_agent_run_feedback.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_agent_runner_ready.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_ai_client.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_ai_intelligence.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_architect_interview.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_architect_v2.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_architecture.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_auditor.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_channel.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_chat_diff_decision.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_chat_runner_openai_compat.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_chat_stdin_protocol.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cleanup_cmd.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cli.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cli_regressions.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cli_workflows_history_drive.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_compliance.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_compliance_governance.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_compressor.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_dispatch.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_e2e_nexus.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_endpoints_cli.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_endpoints_store.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_epistemic.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_backend_switch.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_enforcement.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_integration.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_license.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_sqlite.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_verify_chain_cli.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_writer.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_fallback_chain.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_golden_path.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_importer.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_init_modes.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_integrations.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_integrations_codity.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_intelligence.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_issue_policy_features.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_issue_reporter.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_issues_263_264.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_local_model.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_markdown_deprecation.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_mcp_client.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_mcp_server.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_migration_direction.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_model_router.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_new_modules.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_permissions.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_phase1_4_new.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_phase34_completion.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_project_metrics.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_quality_report.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_rate_limits.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_repl.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_reporting_commands.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_req_248_262.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_req_358_359.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_scaffolder.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_schema_migrations.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_skill_marketplace.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_skills_mcp.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_smoke.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_suggester.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_tools.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_typing_guardrails.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_validator.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_vcs.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_warp_parity.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_warp_parity_followup.py +0 -0
- {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_wi_lifecycle.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specsmith
|
|
3
|
-
Version: 0.17.1.
|
|
3
|
+
Version: 0.17.1.dev684
|
|
4
4
|
Summary: AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, and Aider.
|
|
5
5
|
Author: Layer1Labs Silicon, Inc.
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specsmith"
|
|
7
|
-
version = "0.17.1.
|
|
7
|
+
version = "0.17.1.dev684"
|
|
8
8
|
description = "AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, and Aider."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -27,7 +27,9 @@ left off (extended to cover full epistemic continuity).
|
|
|
27
27
|
from __future__ import annotations
|
|
28
28
|
|
|
29
29
|
import json
|
|
30
|
+
import uuid
|
|
30
31
|
from collections.abc import Sequence
|
|
32
|
+
from datetime import datetime, timezone
|
|
31
33
|
from pathlib import Path
|
|
32
34
|
from typing import Any
|
|
33
35
|
|
|
@@ -62,6 +64,10 @@ def build_context_seed(
|
|
|
62
64
|
records (failed approaches, stale decisions, low-confidence hypotheses) are
|
|
63
65
|
excluded from the context window.
|
|
64
66
|
|
|
67
|
+
REQ-407: ESDB-first ledger snippet (falls back to LEDGER.md).
|
|
68
|
+
REQ-415: auto-tune seed parameters from EFF-CURRENT.
|
|
69
|
+
REQ-416: write context_usage record per build_context_seed() call.
|
|
70
|
+
|
|
65
71
|
Args:
|
|
66
72
|
project_dir: Project root containing ``.specsmith/``.
|
|
67
73
|
char_budget: Maximum total characters across all seed turns.
|
|
@@ -75,9 +81,21 @@ def build_context_seed(
|
|
|
75
81
|
Empty list if no prior context is available.
|
|
76
82
|
"""
|
|
77
83
|
root = Path(project_dir).resolve()
|
|
84
|
+
session_id = uuid.uuid4().hex[:16].upper()
|
|
78
85
|
turns: list[dict[str, Any]] = []
|
|
79
86
|
used = 0
|
|
80
87
|
|
|
88
|
+
# Auto-tune parameters from EFF-CURRENT (REQ-415)
|
|
89
|
+
eff = _load_efficiency_params(root)
|
|
90
|
+
if eff.get("degraded"):
|
|
91
|
+
# Reduce budget when context is degraded to force tighter seeds
|
|
92
|
+
char_budget = int(char_budget * 0.75)
|
|
93
|
+
if eff.get("context_char_efficiency") is not None:
|
|
94
|
+
# Scale max_ledger based on fill efficiency: high fill → fewer ledger lines
|
|
95
|
+
fill_eff = float(eff["context_char_efficiency"])
|
|
96
|
+
if fill_eff > 0.9:
|
|
97
|
+
max_ledger = max(10, max_ledger // 2)
|
|
98
|
+
|
|
81
99
|
# ── 1. Session state snapshot ─────────────────────────────────────
|
|
82
100
|
session_summary = _load_session_summary(root)
|
|
83
101
|
if session_summary:
|
|
@@ -95,7 +113,7 @@ def build_context_seed(
|
|
|
95
113
|
turns.append(t)
|
|
96
114
|
used += len(c)
|
|
97
115
|
|
|
98
|
-
# ── 3. Recent LEDGER entries
|
|
116
|
+
# ── 3. Recent LEDGER entries — ESDB-first (REQ-407) ─────────────────
|
|
99
117
|
ledger_block = _load_ledger_snippet(root, max_lines=max_ledger)
|
|
100
118
|
if ledger_block and used + len(ledger_block) <= char_budget:
|
|
101
119
|
turns.append(
|
|
@@ -106,7 +124,22 @@ def build_context_seed(
|
|
|
106
124
|
)
|
|
107
125
|
used += len(ledger_block)
|
|
108
126
|
|
|
109
|
-
# ── 4.
|
|
127
|
+
# ── 4. Efficiency degradation warning ────────────────────────────────
|
|
128
|
+
if eff.get("degraded"):
|
|
129
|
+
eq_score = eff.get("epistemic_quality_score", 0.0)
|
|
130
|
+
tpc = eff.get("tokens_per_correct_answer")
|
|
131
|
+
baseline = eff.get("baseline_tokens_per_pass")
|
|
132
|
+
warn_parts = ["[EFFICIENCY WARNING: context degraded"]
|
|
133
|
+
if tpc is not None and baseline is not None:
|
|
134
|
+
warn_parts.append(f"tokens/pass={tpc:.0f} vs baseline={baseline:.0f}")
|
|
135
|
+
if eq_score:
|
|
136
|
+
warn_parts.append(f"epistemic_quality={eq_score:.2f}")
|
|
137
|
+
warn_parts.append("— consider specsmith esdb sweep]")
|
|
138
|
+
warn_content = " ".join(warn_parts)
|
|
139
|
+
turns.append({"role": "system", "content": warn_content})
|
|
140
|
+
used += len(warn_content)
|
|
141
|
+
|
|
142
|
+
# ── 5. ESDB records — relevance-based by kind (REQ-399) ──────────────
|
|
110
143
|
esdb_block = _load_esdb_by_kind(
|
|
111
144
|
root,
|
|
112
145
|
max_preflight=max_preflight,
|
|
@@ -123,6 +156,17 @@ def build_context_seed(
|
|
|
123
156
|
),
|
|
124
157
|
}
|
|
125
158
|
)
|
|
159
|
+
used += len(esdb_block)
|
|
160
|
+
|
|
161
|
+
# ── 6. Write context_usage record (REQ-416) ──────────────────────────
|
|
162
|
+
_write_context_usage(
|
|
163
|
+
root,
|
|
164
|
+
session_id=session_id,
|
|
165
|
+
seed_chars=used,
|
|
166
|
+
seed_fill_pct=round(used / max(1, char_budget) * 100.0, 1),
|
|
167
|
+
turns_count=len(turns),
|
|
168
|
+
degraded=bool(eff.get("degraded")),
|
|
169
|
+
)
|
|
126
170
|
|
|
127
171
|
return turns
|
|
128
172
|
|
|
@@ -192,7 +236,34 @@ def _load_conversation_history(
|
|
|
192
236
|
|
|
193
237
|
|
|
194
238
|
def _load_ledger_snippet(root: Path, *, max_lines: int) -> str:
|
|
195
|
-
"""Return the last ``max_lines`` of
|
|
239
|
+
"""Return the last ``max_lines`` of ledger entries — ESDB-first (REQ-407).
|
|
240
|
+
|
|
241
|
+
Query order:
|
|
242
|
+
1. ESDB ``ledger_event`` records (sorted by timestamp desc).
|
|
243
|
+
2. Fall back to LEDGER.md file if ESDB has no ledger_event records.
|
|
244
|
+
"""
|
|
245
|
+
# 1. Try ESDB first
|
|
246
|
+
try:
|
|
247
|
+
from specsmith.esdb import SqliteStore
|
|
248
|
+
|
|
249
|
+
sqlite_path = root / ".specsmith" / "esdb.sqlite3"
|
|
250
|
+
if sqlite_path.exists():
|
|
251
|
+
with SqliteStore(root) as store:
|
|
252
|
+
records = store.query(kind="ledger_event", status="active")
|
|
253
|
+
if records:
|
|
254
|
+
# Sort newest first by timestamp in data, then take last max_lines
|
|
255
|
+
def _ts(r: Any) -> str:
|
|
256
|
+
return str(r.data.get("timestamp") or "")
|
|
257
|
+
|
|
258
|
+
sorted_recs = sorted(records, key=_ts, reverse=True)[:max_lines]
|
|
259
|
+
lines_out = [
|
|
260
|
+
f"{r.data.get('timestamp', '')[:16]} — {r.label[:120]}" for r in sorted_recs
|
|
261
|
+
]
|
|
262
|
+
return "\n".join(lines_out)
|
|
263
|
+
except Exception: # noqa: BLE001
|
|
264
|
+
pass
|
|
265
|
+
|
|
266
|
+
# 2. Fall back to LEDGER.md file
|
|
196
267
|
try:
|
|
197
268
|
candidates = [root / "LEDGER.md", root / "docs" / "LEDGER.md"]
|
|
198
269
|
for path in candidates:
|
|
@@ -310,4 +381,64 @@ def _load_esdb_by_kind(
|
|
|
310
381
|
return "\n".join(lines)
|
|
311
382
|
|
|
312
383
|
|
|
384
|
+
def _load_efficiency_params(root: Path) -> dict[str, Any]:
|
|
385
|
+
"""Load EFF-CURRENT from ESDB and return its data dict (REQ-415).
|
|
386
|
+
|
|
387
|
+
Returns an empty dict on any error (best-effort).
|
|
388
|
+
"""
|
|
389
|
+
try:
|
|
390
|
+
from specsmith.esdb import SqliteStore
|
|
391
|
+
|
|
392
|
+
sqlite_path = root / ".specsmith" / "esdb.sqlite3"
|
|
393
|
+
if not sqlite_path.exists():
|
|
394
|
+
return {}
|
|
395
|
+
with SqliteStore(root) as store:
|
|
396
|
+
rec = store.get("EFF-CURRENT")
|
|
397
|
+
if rec is None:
|
|
398
|
+
return {}
|
|
399
|
+
data = dict(rec.data)
|
|
400
|
+
# Flatten epistemic_quality score for convenience
|
|
401
|
+
eq = data.get("epistemic_quality")
|
|
402
|
+
if isinstance(eq, dict):
|
|
403
|
+
data["epistemic_quality_score"] = eq.get("score", 0.0)
|
|
404
|
+
return data
|
|
405
|
+
except Exception: # noqa: BLE001
|
|
406
|
+
return {}
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _write_context_usage(
|
|
410
|
+
root: Path,
|
|
411
|
+
*,
|
|
412
|
+
session_id: str,
|
|
413
|
+
seed_chars: int,
|
|
414
|
+
seed_fill_pct: float,
|
|
415
|
+
turns_count: int,
|
|
416
|
+
degraded: bool,
|
|
417
|
+
) -> None:
|
|
418
|
+
"""Write a context_usage record to ESDB (REQ-416, best-effort)."""
|
|
419
|
+
try:
|
|
420
|
+
from specsmith.esdb import SqliteRecord, open_default_store
|
|
421
|
+
|
|
422
|
+
rec_id = f"CTX-{session_id}"
|
|
423
|
+
record = SqliteRecord(
|
|
424
|
+
id=rec_id,
|
|
425
|
+
kind="context_usage",
|
|
426
|
+
status="active",
|
|
427
|
+
label=f"seed session={session_id} fill={seed_fill_pct:.1f}%",
|
|
428
|
+
confidence=1.0,
|
|
429
|
+
data={
|
|
430
|
+
"session_id": session_id,
|
|
431
|
+
"seed_chars": seed_chars,
|
|
432
|
+
"seed_fill_pct": seed_fill_pct,
|
|
433
|
+
"turns_count": turns_count,
|
|
434
|
+
"degraded_at_seed": degraded,
|
|
435
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
436
|
+
},
|
|
437
|
+
)
|
|
438
|
+
with open_default_store(root, warn=False) as store:
|
|
439
|
+
store.upsert(record)
|
|
440
|
+
except Exception: # noqa: BLE001
|
|
441
|
+
pass
|
|
442
|
+
|
|
443
|
+
|
|
313
444
|
__all__ = ["build_context_seed"]
|
|
@@ -394,7 +394,9 @@ class AgentRunner:
|
|
|
394
394
|
lines.append(f" {s.icon} {s.name:<10} \u2717 {s.note}")
|
|
395
395
|
lines.append("")
|
|
396
396
|
if active_count == 0:
|
|
397
|
-
lines.append(
|
|
397
|
+
lines.append(
|
|
398
|
+
" \u26a0 No provider available \u2014 commands will return no response."
|
|
399
|
+
)
|
|
398
400
|
else:
|
|
399
401
|
# Show multi-model routing if the router is configured (REQ-389).
|
|
400
402
|
if self._model_router is not None:
|
|
@@ -585,6 +587,28 @@ class AgentRunner:
|
|
|
585
587
|
self._emit_event(type="system", message=hint)
|
|
586
588
|
return None
|
|
587
589
|
|
|
590
|
+
if result is None:
|
|
591
|
+
# All providers failed — give the user an actionable explanation
|
|
592
|
+
# rather than silent emptiness.
|
|
593
|
+
import os as _os
|
|
594
|
+
|
|
595
|
+
host = _os.environ.get("OLLAMA_HOST", DEFAULT_OLLAMA_HOST).rstrip("/")
|
|
596
|
+
if _ollama_alive(host):
|
|
597
|
+
model = _pick_ollama_model(host)
|
|
598
|
+
hint = (
|
|
599
|
+
f"Ollama is running but returned no response "
|
|
600
|
+
f"(model: {model}). "
|
|
601
|
+
"Try: ollama run " + model
|
|
602
|
+
)
|
|
603
|
+
else:
|
|
604
|
+
hint = (
|
|
605
|
+
"No LLM provider available. Options:\n"
|
|
606
|
+
" • Start Ollama: ollama serve\n"
|
|
607
|
+
" • Set ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY"
|
|
608
|
+
)
|
|
609
|
+
self._emit_event(type="system", message=hint)
|
|
610
|
+
return None
|
|
611
|
+
|
|
588
612
|
# Aggregate metrics into the session state (C1).
|
|
589
613
|
# ``run_chat`` now reports tokens_in / tokens_out / cost_usd off the
|
|
590
614
|
# provider response (Ollama prompt_eval_count + eval_count, OpenAI
|
|
@@ -604,6 +628,23 @@ class AgentRunner:
|
|
|
604
628
|
)
|
|
605
629
|
self._state.elapsed_minutes = round((time.time() - self._started_at) / 60.0, 2)
|
|
606
630
|
|
|
631
|
+
# Write token_metric to ESDB (REQ-410) — best-effort, never blocks.
|
|
632
|
+
if tokens_in or tokens_out:
|
|
633
|
+
try:
|
|
634
|
+
from specsmith.esdb_writer import write_token_metric
|
|
635
|
+
|
|
636
|
+
write_token_metric(
|
|
637
|
+
self.project_dir,
|
|
638
|
+
input_tokens=tokens_in,
|
|
639
|
+
output_tokens=tokens_out,
|
|
640
|
+
cost_usd=cost_usd,
|
|
641
|
+
model=str(getattr(result, "provider", "") if result else ""),
|
|
642
|
+
command_source=activity or "chat",
|
|
643
|
+
work_item_id=str(getattr(self._state, "active_work_item_id", "") or ""),
|
|
644
|
+
)
|
|
645
|
+
except Exception: # noqa: BLE001
|
|
646
|
+
pass
|
|
647
|
+
|
|
607
648
|
if result is not None:
|
|
608
649
|
self._history.append({"role": "user", "text": utterance})
|
|
609
650
|
self._history.append({"role": "agent", "text": result.summary})
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
+
"""specsmith.agent.token_pricing — static per-token cost lookup.
|
|
4
|
+
|
|
5
|
+
Provides a single function :func:`cost_for_tokens` that returns the estimated
|
|
6
|
+
USD cost for a given (provider, model, input_tokens, output_tokens) tuple.
|
|
7
|
+
|
|
8
|
+
Design contract
|
|
9
|
+
---------------
|
|
10
|
+
- ``ollama`` provider (and its aliases ``llamacpp``, ``vllm``, ``lmstudio``)
|
|
11
|
+
always returns **0.0** — local inference is free; this is intentional and
|
|
12
|
+
correct, not a bug or missing data.
|
|
13
|
+
- Known cloud models (OpenAI, Anthropic, Google) use a static pricing table
|
|
14
|
+
updated to Q2 2026 list prices.
|
|
15
|
+
- Unknown providers/models fall back to a conservative default rate so
|
|
16
|
+
``cost_of_pass`` analysis degrades gracefully rather than crashing.
|
|
17
|
+
|
|
18
|
+
Pricing source
|
|
19
|
+
--------------
|
|
20
|
+
Q2 2026 provider pricing pages. All figures are in USD per 1 M tokens.
|
|
21
|
+
Update this table when provider pricing changes (bump the table version comment).
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from typing import Any
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Pricing table — (input_usd_per_1M, output_usd_per_1M)
|
|
30
|
+
# Table version: 2026-Q2
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
#: Providers that are always zero-cost (local inference).
|
|
34
|
+
_FREE_PROVIDERS: frozenset[str] = frozenset({"ollama", "llamacpp", "vllm", "lmstudio", "local"})
|
|
35
|
+
|
|
36
|
+
#: Static pricing table. Keys are normalised model name substrings matched
|
|
37
|
+
#: from longest to shortest so that more-specific keys win over generic ones.
|
|
38
|
+
_PRICING_PER_1M: dict[str, tuple[float, float]] = {
|
|
39
|
+
# ── OpenAI GPT-4 family ────────────────────────────────────────────────
|
|
40
|
+
"gpt-4o-mini": (0.15, 0.60),
|
|
41
|
+
"gpt-4o": (2.50, 10.00),
|
|
42
|
+
"gpt-4.1-nano": (0.10, 0.40),
|
|
43
|
+
"gpt-4.1-mini": (0.40, 1.60),
|
|
44
|
+
"gpt-4.1": (2.00, 8.00),
|
|
45
|
+
"gpt-4-turbo": (10.00, 30.00),
|
|
46
|
+
# ── OpenAI GPT-5 family ────────────────────────────────────────────────
|
|
47
|
+
"gpt-5-nano": (0.50, 2.00),
|
|
48
|
+
"gpt-5-mini": (2.00, 8.00),
|
|
49
|
+
"gpt-5-pro": (50.00, 200.00),
|
|
50
|
+
"gpt-5.4-nano": (0.30, 1.20),
|
|
51
|
+
"gpt-5.4-mini": (1.00, 4.00),
|
|
52
|
+
"gpt-5.4-pro": (20.00, 80.00),
|
|
53
|
+
"gpt-5.4": (5.00, 20.00),
|
|
54
|
+
"gpt-5.5-pro": (15.00, 60.00),
|
|
55
|
+
"gpt-5.5": (3.00, 12.00),
|
|
56
|
+
"gpt-5.2-codex": (10.00, 40.00),
|
|
57
|
+
"gpt-5.2-pro": (40.00, 160.00),
|
|
58
|
+
"gpt-5.2": (10.00, 40.00),
|
|
59
|
+
"gpt-5.3-codex": (8.00, 32.00),
|
|
60
|
+
"gpt-5.1": (12.00, 48.00),
|
|
61
|
+
"gpt-5-codex": (15.00, 60.00),
|
|
62
|
+
"gpt-5": (15.00, 60.00),
|
|
63
|
+
# ── OpenAI reasoning ──────────────────────────────────────────────────
|
|
64
|
+
"o4-mini": (1.10, 4.40),
|
|
65
|
+
"o3-mini": (1.10, 4.40),
|
|
66
|
+
"o3": (10.00, 40.00),
|
|
67
|
+
"o1": (15.00, 60.00),
|
|
68
|
+
# ── Anthropic ─────────────────────────────────────────────────────────
|
|
69
|
+
"claude-haiku-4-5": (0.25, 1.25),
|
|
70
|
+
"claude-haiku": (0.25, 1.25),
|
|
71
|
+
"claude-sonnet-4-5": (3.00, 15.00),
|
|
72
|
+
"claude-sonnet-4-6": (3.00, 15.00),
|
|
73
|
+
"claude-sonnet": (3.00, 15.00),
|
|
74
|
+
"claude-opus-4-5": (15.00, 75.00),
|
|
75
|
+
"claude-opus-4-6": (15.00, 75.00),
|
|
76
|
+
"claude-opus": (15.00, 75.00),
|
|
77
|
+
# ── Google ────────────────────────────────────────────────────────────
|
|
78
|
+
"gemini-3.5-flash": (0.15, 0.60),
|
|
79
|
+
"gemini-3-flash": (0.35, 1.05),
|
|
80
|
+
"gemini-flash": (0.075, 0.30),
|
|
81
|
+
"gemini-3.1-pro": (1.25, 5.00),
|
|
82
|
+
"gemini-pro": (1.25, 5.00),
|
|
83
|
+
# ── Conservative fallback ─────────────────────────────────────────────
|
|
84
|
+
"unknown": (3.00, 15.00),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _lookup_rates(model: str) -> tuple[float, float]:
|
|
89
|
+
"""Return (input_usd_per_1M, output_usd_per_1M) for *model*.
|
|
90
|
+
|
|
91
|
+
Tries an exact key match first, then a longest-substring match, and
|
|
92
|
+
finally falls back to the ``"unknown"`` conservative default.
|
|
93
|
+
"""
|
|
94
|
+
key = model.strip().lower()
|
|
95
|
+
if key in _PRICING_PER_1M:
|
|
96
|
+
return _PRICING_PER_1M[key]
|
|
97
|
+
# Longest-prefix / substring match so that "gpt-4o-mini-2026-04-09"
|
|
98
|
+
# still resolves to "gpt-4o-mini".
|
|
99
|
+
best_match = ""
|
|
100
|
+
for table_key in _PRICING_PER_1M:
|
|
101
|
+
if table_key in key and len(table_key) > len(best_match):
|
|
102
|
+
best_match = table_key
|
|
103
|
+
if best_match:
|
|
104
|
+
return _PRICING_PER_1M[best_match]
|
|
105
|
+
return _PRICING_PER_1M["unknown"]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def cost_for_tokens(
|
|
109
|
+
provider: str,
|
|
110
|
+
model: str,
|
|
111
|
+
input_tokens: int,
|
|
112
|
+
output_tokens: int,
|
|
113
|
+
) -> float:
|
|
114
|
+
"""Return estimated USD cost for a single LLM call.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
provider: Provider name (e.g. ``"ollama"``, ``"openai"``, ``"anthropic"``).
|
|
118
|
+
model: Model name or slug (e.g. ``"gpt-4o"``, ``"qwen2.5-coder:14b"``).
|
|
119
|
+
input_tokens: Number of prompt/context tokens consumed.
|
|
120
|
+
output_tokens: Number of generated/completion tokens.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Estimated cost in USD. Always ``0.0`` for local/free providers
|
|
124
|
+
(Ollama, llamacpp, vllm, lmstudio, local). Returns ``0.0`` when
|
|
125
|
+
both token counts are zero regardless of provider.
|
|
126
|
+
|
|
127
|
+
Examples::
|
|
128
|
+
|
|
129
|
+
>>> cost_for_tokens("ollama", "qwen2.5-coder:14b", 1000, 500)
|
|
130
|
+
0.0
|
|
131
|
+
>>> cost_for_tokens("openai", "gpt-4o-mini", 1_000_000, 0)
|
|
132
|
+
0.15
|
|
133
|
+
>>> cost_for_tokens("anthropic", "claude-haiku-4-5", 0, 1_000_000)
|
|
134
|
+
1.25
|
|
135
|
+
"""
|
|
136
|
+
if not provider and not model:
|
|
137
|
+
return 0.0
|
|
138
|
+
if (provider or "").strip().lower() in _FREE_PROVIDERS:
|
|
139
|
+
return 0.0
|
|
140
|
+
if input_tokens == 0 and output_tokens == 0:
|
|
141
|
+
return 0.0
|
|
142
|
+
inp_per_m, out_per_m = _lookup_rates(model)
|
|
143
|
+
return (input_tokens * inp_per_m + output_tokens * out_per_m) / 1_000_000
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def cost_for_tokens_breakdown(
|
|
147
|
+
provider: str,
|
|
148
|
+
model: str,
|
|
149
|
+
input_tokens: int,
|
|
150
|
+
output_tokens: int,
|
|
151
|
+
) -> tuple[float, float, float]:
|
|
152
|
+
"""Return ``(input_cost_usd, output_cost_usd, total_cost_usd)``."""
|
|
153
|
+
if (provider or "").strip().lower() in _FREE_PROVIDERS:
|
|
154
|
+
return 0.0, 0.0, 0.0
|
|
155
|
+
inp_per_m, out_per_m = _lookup_rates(model)
|
|
156
|
+
inp_cost = input_tokens * inp_per_m / 1_000_000
|
|
157
|
+
out_cost = output_tokens * out_per_m / 1_000_000
|
|
158
|
+
return inp_cost, out_cost, inp_cost + out_cost
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def tokens_per_correct_answer(
|
|
162
|
+
records: list[Any],
|
|
163
|
+
*,
|
|
164
|
+
token_attr: str = "tokens_total",
|
|
165
|
+
passed_attr: str = "passed",
|
|
166
|
+
) -> float | None:
|
|
167
|
+
"""Compute mean tokens consumed per correct (passing) answer.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
records: Sequence of record objects (e.g. :class:`MetricsRecord` or
|
|
171
|
+
:class:`RunResult`) with numeric ``token_attr`` and bool
|
|
172
|
+
``passed_attr`` attributes.
|
|
173
|
+
token_attr: Attribute name for total token count.
|
|
174
|
+
passed_attr: Attribute name for pass/fail boolean.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
Mean total tokens among passing records, or ``None`` if no passing
|
|
178
|
+
records exist.
|
|
179
|
+
"""
|
|
180
|
+
passing = [r for r in records if getattr(r, passed_attr, False)]
|
|
181
|
+
if not passing:
|
|
182
|
+
return None
|
|
183
|
+
totals = [getattr(r, token_attr, 0) for r in passing]
|
|
184
|
+
return sum(totals) / len(totals)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
__all__ = [
|
|
188
|
+
"cost_for_tokens",
|
|
189
|
+
"cost_for_tokens_breakdown",
|
|
190
|
+
"tokens_per_correct_answer",
|
|
191
|
+
]
|
|
@@ -554,8 +554,9 @@ def check_ledger_health(root: Path) -> list[AuditResult]:
|
|
|
554
554
|
|
|
555
555
|
|
|
556
556
|
# Default thresholds (used when no project type is detected)
|
|
557
|
+
# AGENTS.md: raised to 250 (template now generates ~202 lines with Parallel Agents section)
|
|
557
558
|
_DEFAULT_THRESHOLDS: dict[str, int] = {
|
|
558
|
-
"AGENTS.md":
|
|
559
|
+
"AGENTS.md": 250,
|
|
559
560
|
"docs/governance/RULES.md": 800,
|
|
560
561
|
"docs/governance/SESSION-PROTOCOL.md": 400,
|
|
561
562
|
"docs/governance/LIFECYCLE.md": 200,
|