shellbrain 0.1.25__tar.gz → 0.1.26__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.
- {shellbrain-0.1.25 → shellbrain-0.1.26}/PKG-INFO +1 -1
- shellbrain-0.1.26/app/migrations/versions/20260422_0015_problem_runs.py +101 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/cli/main.py +34 -50
- shellbrain-0.1.26/app/periphery/db/models/problem_runs.py +60 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/registry.py +2 -1
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/views.py +212 -0
- shellbrain-0.1.26/app/periphery/metrics/pager.py +250 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/metrics/queries.py +23 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/metrics/service.py +8 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/pyproject.toml +1 -1
- {shellbrain-0.1.25 → shellbrain-0.1.26}/shellbrain.egg-info/PKG-INFO +1 -1
- {shellbrain-0.1.25 → shellbrain-0.1.26}/shellbrain.egg-info/SOURCES.txt +3 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/README.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/__main__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/_dsn_resolution.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/admin_db.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/config.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/create_policy.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/db.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/embeddings.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/home.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/migrations.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/read_policy.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/repos.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/retrieval.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/thresholds.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/update_policy.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/boot/use_cases.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/config/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/config/defaults/create_policy.yaml +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/config/defaults/read_policy.yaml +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/config/defaults/runtime.yaml +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/config/defaults/thresholds.yaml +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/config/defaults/update_policy.yaml +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/config/loader.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/contracts/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/contracts/concepts.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/contracts/errors.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/contracts/requests.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/contracts/responses.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/associations.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/concepts.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/episodes.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/evidence.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/facts.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/guidance.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/identity.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/memory.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/runtime_context.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/session_state.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/telemetry.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/entities/utility.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/clock.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/config.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/embeddings.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/idgen.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/repos.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/retrieval.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/session_state_store.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/interfaces/unit_of_work.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/_shared/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/_shared/executor.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/_shared/side_effects.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/create_policy/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/create_policy/pipeline.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/bm25.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/context_pack_builder.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/expansion.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/fusion_rrf.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/lexical_query.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/pipeline.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/scoring.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/read_policy/seed_retrieval.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/update_policy/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/policies/update_policy/pipeline.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/build_guidance.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/create_memory.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/manage_concepts.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/manage_session_state.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/read_concepts.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/read_memory.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/record_episode_sync_telemetry.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/record_model_usage_telemetry.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/record_operation_telemetry.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/sync_episode.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/core/use_cases/update_memory.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/env.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260226_0001_initial_schema.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260312_0002_add_hard_invariants.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260312_0003_drop_create_confidence.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260313_0004_episode_sync_hardening.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260313_0005_evidence_episode_event_refs.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260318_0006_usage_telemetry_schema.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260319_0007_identity_session_guidance.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260320_0008_instance_metadata_and_backup_safety.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260410_0009_frontier_memory_family.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260414_0010_model_usage_telemetry.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260414_0011_usage_problem_tokens_multi_solution_metrics.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260415_0012_read_pack_cost_and_read_roi.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260421_0013_concept_context_graph.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/20260422_0014_concept_read_telemetry.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/migrations/versions/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/claude/CLAUDE.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/claude/skills/shellbrain-session-start/SKILL.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/claude/skills/shellbrain-usage-review/SKILL.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/AGENTS.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-session-start/SKILL.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-session-start/agents/openai.yaml +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-session-start/assets/shellbrain-large.svg +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-session-start/assets/shellbrain-small.svg +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-session-start/assets/shellbrain_logo.png +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-session-start/references/request-shapes.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-session-start/references/session-workflow.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-usage-review/SKILL.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-usage-review/agents/openai.yaml +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-usage-review/assets/shellbrain-small.svg +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/codex/shellbrain-usage-review/assets/shellbrain_logo.png +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/cursor/skills/shellbrain-session-start/SKILL.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/onboarding_assets/cursor/skills/shellbrain-usage-review/SKILL.md +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/agent_behavior_analysis.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/analytics.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/analytics_diagnostics.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/analytics_queries.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/backup.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/destructive_guard.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/doctor.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/external_runtime.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/init.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/init_errors.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/instance_guard.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/machine_state.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/managed_runtime.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/model_usage_backfill.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/privileges.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/repo_state.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/restore.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/storage_setup.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/admin/upgrade.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/cli/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/cli/handlers.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/cli/hydration.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/cli/presenter_json.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/cli/schema_validation.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/engine.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/associations.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/concepts.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/episodes.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/evidence.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/experiences.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/instance_metadata.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/memories.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/metadata.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/telemetry.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/models/utility.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/associations_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/concepts_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/episodes_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/evidence_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/experiences_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/memories_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/read_policy_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/telemetry_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/relational/utility_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/semantic/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/semantic/keyword_retrieval_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/repos/semantic/semantic_retrieval_repo.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/session.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/db/uow.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/embeddings/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/embeddings/local_provider.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/embeddings/query_vector_search.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/claude_code.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/codex.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/cursor.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/launcher.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/model_usage.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/normalization.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/poller.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/poller_lock.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/source_discovery.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/episodes/tool_filter.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/identity/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/identity/claude_hook_install.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/identity/claude_runtime.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/identity/codex_runtime.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/identity/compatibility.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/identity/cursor_statusline.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/identity/resolver.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/metrics/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/metrics/artifacts.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/metrics/browser.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/metrics/render_html.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/onboarding/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/onboarding/host_assets.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/session_state/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/session_state/file_store.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/telemetry/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/telemetry/operation_summary.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/telemetry/session_selection.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/telemetry/sync_summary.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/validation/__init__.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/validation/integrity_validation.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/app/periphery/validation/semantic_validation.py +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/setup.cfg +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/shellbrain.egg-info/dependency_links.txt +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/shellbrain.egg-info/entry_points.txt +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/shellbrain.egg-info/requires.txt +0 -0
- {shellbrain-0.1.25 → shellbrain-0.1.26}/shellbrain.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Add explicit problem-run token metrics."""
|
|
2
|
+
|
|
3
|
+
from alembic import op
|
|
4
|
+
|
|
5
|
+
from app.periphery.db.models.views import (
|
|
6
|
+
USAGE_PROBLEM_READ_ROI_LEGACY_SQL,
|
|
7
|
+
USAGE_PROBLEM_RUN_TOKENS_SQL,
|
|
8
|
+
USAGE_PROBLEM_TOKENS_LEGACY_SQL,
|
|
9
|
+
USAGE_READ_BEFORE_SOLVE_ROI_LEGACY_SQL,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
revision = "20260422_0015"
|
|
13
|
+
down_revision = "20260422_0014"
|
|
14
|
+
branch_labels = None
|
|
15
|
+
depends_on = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _unsuffixed_proxy_sql(sql: str) -> str:
|
|
19
|
+
"""Return the pre-legacy view name for downgrade compatibility."""
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
sql.replace("usage_read_before_solve_roi_legacy", "usage_read_before_solve_roi")
|
|
23
|
+
.replace("usage_problem_read_roi_legacy", "usage_problem_read_roi")
|
|
24
|
+
.replace("usage_problem_tokens_legacy", "usage_problem_tokens")
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def upgrade() -> None:
|
|
29
|
+
"""Create problem-run windows and rename memory-derived token proxies."""
|
|
30
|
+
|
|
31
|
+
op.execute(
|
|
32
|
+
"""
|
|
33
|
+
DROP VIEW IF EXISTS usage_read_before_solve_roi;
|
|
34
|
+
DROP VIEW IF EXISTS usage_problem_read_roi;
|
|
35
|
+
DROP VIEW IF EXISTS usage_problem_tokens;
|
|
36
|
+
|
|
37
|
+
CREATE TABLE problem_runs (
|
|
38
|
+
id TEXT PRIMARY KEY,
|
|
39
|
+
repo_id TEXT NOT NULL,
|
|
40
|
+
thread_id TEXT,
|
|
41
|
+
host_app TEXT,
|
|
42
|
+
host_session_key TEXT,
|
|
43
|
+
episode_id TEXT REFERENCES episodes(id) ON DELETE SET NULL,
|
|
44
|
+
status TEXT NOT NULL,
|
|
45
|
+
opened_at TIMESTAMPTZ NOT NULL,
|
|
46
|
+
closed_at TIMESTAMPTZ,
|
|
47
|
+
opened_by TEXT NOT NULL,
|
|
48
|
+
closed_by TEXT,
|
|
49
|
+
problem_memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL,
|
|
50
|
+
solution_memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL,
|
|
51
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
52
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
53
|
+
CONSTRAINT ck_problem_runs_status CHECK (status IN ('open', 'closed', 'abandoned')),
|
|
54
|
+
CONSTRAINT ck_problem_runs_opened_by CHECK (opened_by IN ('worker', 'librarian', 'manual', 'system')),
|
|
55
|
+
CONSTRAINT ck_problem_runs_closed_by CHECK (closed_by IS NULL OR closed_by IN ('worker', 'librarian', 'manual', 'system')),
|
|
56
|
+
CONSTRAINT ck_problem_runs_closed_after_opened CHECK (closed_at IS NULL OR closed_at >= opened_at),
|
|
57
|
+
CONSTRAINT ck_problem_runs_status_closed_at CHECK (
|
|
58
|
+
(
|
|
59
|
+
status = 'open'
|
|
60
|
+
AND closed_at IS NULL
|
|
61
|
+
) OR (
|
|
62
|
+
status IN ('closed', 'abandoned')
|
|
63
|
+
AND closed_at IS NOT NULL
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
CREATE INDEX idx_problem_runs_repo_thread_window
|
|
69
|
+
ON problem_runs(repo_id, thread_id, opened_at, closed_at);
|
|
70
|
+
CREATE INDEX idx_problem_runs_repo_host_session_window
|
|
71
|
+
ON problem_runs(repo_id, host_app, host_session_key, opened_at, closed_at);
|
|
72
|
+
CREATE INDEX idx_problem_runs_repo_status_opened_at
|
|
73
|
+
ON problem_runs(repo_id, status, opened_at);
|
|
74
|
+
CREATE INDEX idx_problem_runs_problem_memory
|
|
75
|
+
ON problem_runs(problem_memory_id);
|
|
76
|
+
CREATE INDEX idx_problem_runs_solution_memory
|
|
77
|
+
ON problem_runs(solution_memory_id);
|
|
78
|
+
"""
|
|
79
|
+
)
|
|
80
|
+
op.execute(USAGE_PROBLEM_TOKENS_LEGACY_SQL)
|
|
81
|
+
op.execute(USAGE_PROBLEM_READ_ROI_LEGACY_SQL)
|
|
82
|
+
op.execute(USAGE_READ_BEFORE_SOLVE_ROI_LEGACY_SQL)
|
|
83
|
+
op.execute(USAGE_PROBLEM_RUN_TOKENS_SQL)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def downgrade() -> None:
|
|
87
|
+
"""Drop problem-run metrics and restore the previous proxy view names."""
|
|
88
|
+
|
|
89
|
+
op.execute(
|
|
90
|
+
"""
|
|
91
|
+
DROP VIEW IF EXISTS usage_problem_run_tokens;
|
|
92
|
+
DROP TABLE IF EXISTS problem_runs;
|
|
93
|
+
|
|
94
|
+
DROP VIEW IF EXISTS usage_read_before_solve_roi_legacy;
|
|
95
|
+
DROP VIEW IF EXISTS usage_problem_read_roi_legacy;
|
|
96
|
+
DROP VIEW IF EXISTS usage_problem_tokens_legacy;
|
|
97
|
+
"""
|
|
98
|
+
)
|
|
99
|
+
op.execute(_unsuffixed_proxy_sql(USAGE_PROBLEM_TOKENS_LEGACY_SQL))
|
|
100
|
+
op.execute(_unsuffixed_proxy_sql(USAGE_PROBLEM_READ_ROI_LEGACY_SQL))
|
|
101
|
+
op.execute(_unsuffixed_proxy_sql(USAGE_READ_BEFORE_SOLVE_ROI_LEGACY_SQL))
|
|
@@ -60,7 +60,7 @@ _TOP_LEVEL_HELP = dedent(
|
|
|
60
60
|
Examples:
|
|
61
61
|
shellbrain init
|
|
62
62
|
shellbrain upgrade
|
|
63
|
-
shellbrain metrics
|
|
63
|
+
shellbrain metrics
|
|
64
64
|
shellbrain read --json '{"query":"Have we seen this migration lock timeout before?","kinds":["problem","solution","failed_tactic"]}'
|
|
65
65
|
shellbrain read --json '{"query":"What repo constraints or user preferences matter for this auth refactor?","kinds":["fact","preference","change"]}'
|
|
66
66
|
shellbrain events --json '{"limit":10}'
|
|
@@ -260,12 +260,10 @@ _BACKFILL_TOKEN_USAGE_HELP = dedent(
|
|
|
260
260
|
|
|
261
261
|
_METRICS_HELP = dedent(
|
|
262
262
|
"""\
|
|
263
|
-
Generate
|
|
263
|
+
Generate lightweight metrics snapshots, write local artifacts, and browse repos with arrow keys.
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
Example:
|
|
266
266
|
shellbrain metrics
|
|
267
|
-
shellbrain metrics --days 30
|
|
268
|
-
shellbrain metrics --days 14 --no-open
|
|
269
267
|
"""
|
|
270
268
|
)
|
|
271
269
|
|
|
@@ -386,23 +384,11 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
386
384
|
|
|
387
385
|
metrics_parser = subparsers.add_parser(
|
|
388
386
|
"metrics",
|
|
389
|
-
help="
|
|
390
|
-
description="Generate
|
|
387
|
+
help="Browse Shellbrain metrics across repos.",
|
|
388
|
+
description="Generate local metrics snapshots and browse one repo at a time in the terminal.",
|
|
391
389
|
epilog=_METRICS_HELP,
|
|
392
390
|
formatter_class=_HelpFormatter,
|
|
393
391
|
)
|
|
394
|
-
_add_repo_context_arguments(metrics_parser, suppress_default=True)
|
|
395
|
-
metrics_parser.add_argument(
|
|
396
|
-
"--days",
|
|
397
|
-
type=int,
|
|
398
|
-
default=30,
|
|
399
|
-
help="Number of trailing days to include in the snapshot. Defaults to 30.",
|
|
400
|
-
)
|
|
401
|
-
metrics_parser.add_argument(
|
|
402
|
-
"--no-open",
|
|
403
|
-
action="store_true",
|
|
404
|
-
help="Generate artifacts without opening the dashboard in the browser.",
|
|
405
|
-
)
|
|
406
392
|
|
|
407
393
|
create_parser = subparsers.add_parser(
|
|
408
394
|
"create",
|
|
@@ -877,7 +863,7 @@ def _run_admin_command(args: argparse.Namespace) -> int:
|
|
|
877
863
|
|
|
878
864
|
|
|
879
865
|
def _run_metrics_command(args: argparse.Namespace) -> int:
|
|
880
|
-
"""Generate
|
|
866
|
+
"""Generate metrics snapshots and artifacts for one or many repos."""
|
|
881
867
|
|
|
882
868
|
try:
|
|
883
869
|
from app.boot.admin_db import get_optional_admin_db_dsn
|
|
@@ -885,43 +871,41 @@ def _run_metrics_command(args: argparse.Namespace) -> int:
|
|
|
885
871
|
from app.periphery.db.engine import get_engine
|
|
886
872
|
from app.periphery.metrics.artifacts import write_metrics_artifacts
|
|
887
873
|
from app.periphery.metrics.browser import open_metrics_dashboard
|
|
874
|
+
from app.periphery.metrics.pager import present_metrics_repo_pager
|
|
888
875
|
from app.periphery.metrics.render_html import render_metrics_dashboard
|
|
889
|
-
from app.periphery.metrics.service import build_metrics_snapshot
|
|
876
|
+
from app.periphery.metrics.service import build_metrics_snapshot, list_metrics_repo_ids
|
|
877
|
+
|
|
878
|
+
if bool(getattr(args, "repo_id", None) or getattr(args, "repo_root", None) or getattr(args, "no_sync", False)):
|
|
879
|
+
raise ValueError("`shellbrain metrics` does not accept options. Run `shellbrain metrics`.")
|
|
890
880
|
|
|
891
|
-
repo_context = resolve_repo_context(
|
|
892
|
-
repo_root_arg=getattr(args, "repo_root", None),
|
|
893
|
-
repo_id_arg=getattr(args, "repo_id", None),
|
|
894
|
-
)
|
|
895
881
|
_warn_or_fail_on_unsafe_app_role()
|
|
896
|
-
_ensure_repo_registration_for_operation(
|
|
897
|
-
repo_context=repo_context,
|
|
898
|
-
repo_id_override=getattr(args, "repo_id", None),
|
|
899
|
-
)
|
|
900
882
|
dsn = get_optional_db_dsn() or get_optional_admin_db_dsn()
|
|
901
883
|
if not dsn:
|
|
902
884
|
raise RuntimeError("Shellbrain database is not configured. Run `shellbrain init` first.")
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
885
|
+
engine = get_engine(dsn)
|
|
886
|
+
|
|
887
|
+
target_repo_ids = list_metrics_repo_ids(engine=engine)
|
|
888
|
+
if not target_repo_ids:
|
|
889
|
+
print("No tracked repos found in metrics telemetry yet.")
|
|
890
|
+
return 0
|
|
891
|
+
|
|
892
|
+
entries: list[dict[str, Any]] = []
|
|
893
|
+
window_days = 30
|
|
894
|
+
for repo_id in target_repo_ids:
|
|
895
|
+
snapshot = build_metrics_snapshot(
|
|
896
|
+
engine=engine,
|
|
897
|
+
repo_id=repo_id,
|
|
898
|
+
days=window_days,
|
|
899
|
+
)
|
|
900
|
+
html = render_metrics_dashboard(snapshot)
|
|
901
|
+
paths = write_metrics_artifacts(repo_id=repo_id, snapshot=snapshot, html=html)
|
|
902
|
+
entries.append({"snapshot": snapshot, "paths": paths})
|
|
903
|
+
|
|
904
|
+
print(f"Generated Shellbrain metrics for {len(entries)} repos")
|
|
905
|
+
print(f"Window: last {window_days} days")
|
|
918
906
|
print("Artifacts: updated in place")
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
elif opened_dashboard:
|
|
922
|
-
print("Browser: opened dashboard")
|
|
923
|
-
else:
|
|
924
|
-
print("Browser: could not open automatically")
|
|
907
|
+
print("Browser: press 'o' in the viewer to open the current dashboard")
|
|
908
|
+
present_metrics_repo_pager(entries=entries, open_dashboard=open_metrics_dashboard)
|
|
925
909
|
return 0
|
|
926
910
|
except (RuntimeError, ValueError) as exc:
|
|
927
911
|
print(str(exc), file=sys.stderr)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""SQLAlchemy Core table for explicit problem-run telemetry windows."""
|
|
2
|
+
|
|
3
|
+
from sqlalchemy import CheckConstraint, Column, ForeignKey, Index, String, Table, text
|
|
4
|
+
from sqlalchemy.dialects.postgresql import TIMESTAMP
|
|
5
|
+
|
|
6
|
+
from app.periphery.db.models.metadata import metadata
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
_PROBLEM_RUN_STATUSES = "'open', 'closed', 'abandoned'"
|
|
10
|
+
_PROBLEM_RUN_ACTORS = "'worker', 'librarian', 'manual', 'system'"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
problem_runs = Table(
|
|
14
|
+
"problem_runs",
|
|
15
|
+
metadata,
|
|
16
|
+
Column("id", String, primary_key=True),
|
|
17
|
+
Column("repo_id", String, nullable=False),
|
|
18
|
+
Column("thread_id", String),
|
|
19
|
+
Column("host_app", String),
|
|
20
|
+
Column("host_session_key", String),
|
|
21
|
+
Column("episode_id", String, ForeignKey("episodes.id", ondelete="SET NULL")),
|
|
22
|
+
Column("status", String, nullable=False),
|
|
23
|
+
Column("opened_at", TIMESTAMP(timezone=True), nullable=False),
|
|
24
|
+
Column("closed_at", TIMESTAMP(timezone=True)),
|
|
25
|
+
Column("opened_by", String, nullable=False),
|
|
26
|
+
Column("closed_by", String),
|
|
27
|
+
Column("problem_memory_id", String, ForeignKey("memories.id", ondelete="SET NULL")),
|
|
28
|
+
Column("solution_memory_id", String, ForeignKey("memories.id", ondelete="SET NULL")),
|
|
29
|
+
Column("created_at", TIMESTAMP(timezone=True), nullable=False, server_default=text("NOW()")),
|
|
30
|
+
Column("updated_at", TIMESTAMP(timezone=True), nullable=False, server_default=text("NOW()")),
|
|
31
|
+
CheckConstraint(f"status IN ({_PROBLEM_RUN_STATUSES})", name="ck_problem_runs_status"),
|
|
32
|
+
CheckConstraint(f"opened_by IN ({_PROBLEM_RUN_ACTORS})", name="ck_problem_runs_opened_by"),
|
|
33
|
+
CheckConstraint(f"closed_by IS NULL OR closed_by IN ({_PROBLEM_RUN_ACTORS})", name="ck_problem_runs_closed_by"),
|
|
34
|
+
CheckConstraint("closed_at IS NULL OR closed_at >= opened_at", name="ck_problem_runs_closed_after_opened"),
|
|
35
|
+
CheckConstraint(
|
|
36
|
+
"""
|
|
37
|
+
(
|
|
38
|
+
status = 'open'
|
|
39
|
+
AND closed_at IS NULL
|
|
40
|
+
) OR (
|
|
41
|
+
status IN ('closed', 'abandoned')
|
|
42
|
+
AND closed_at IS NOT NULL
|
|
43
|
+
)
|
|
44
|
+
""",
|
|
45
|
+
name="ck_problem_runs_status_closed_at",
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
Index("idx_problem_runs_repo_thread_window", problem_runs.c.repo_id, problem_runs.c.thread_id, problem_runs.c.opened_at, problem_runs.c.closed_at)
|
|
50
|
+
Index(
|
|
51
|
+
"idx_problem_runs_repo_host_session_window",
|
|
52
|
+
problem_runs.c.repo_id,
|
|
53
|
+
problem_runs.c.host_app,
|
|
54
|
+
problem_runs.c.host_session_key,
|
|
55
|
+
problem_runs.c.opened_at,
|
|
56
|
+
problem_runs.c.closed_at,
|
|
57
|
+
)
|
|
58
|
+
Index("idx_problem_runs_repo_status_opened_at", problem_runs.c.repo_id, problem_runs.c.status, problem_runs.c.opened_at)
|
|
59
|
+
Index("idx_problem_runs_problem_memory", problem_runs.c.problem_memory_id)
|
|
60
|
+
Index("idx_problem_runs_solution_memory", problem_runs.c.solution_memory_id)
|
|
@@ -8,12 +8,13 @@ from app.periphery.db.models import (
|
|
|
8
8
|
experiences,
|
|
9
9
|
instance_metadata,
|
|
10
10
|
memories,
|
|
11
|
+
problem_runs,
|
|
11
12
|
telemetry,
|
|
12
13
|
utility,
|
|
13
14
|
)
|
|
14
15
|
from app.periphery.db.models.metadata import metadata
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
_ = (associations, concepts, episodes, evidence, experiences, instance_metadata, memories, telemetry, utility)
|
|
18
|
+
_ = (associations, concepts, episodes, evidence, experiences, instance_metadata, memories, problem_runs, telemetry, utility)
|
|
18
19
|
|
|
19
20
|
target_metadata = metadata
|
|
@@ -616,6 +616,218 @@ GROUP BY repo_id, solve_window, read_cohort;
|
|
|
616
616
|
"""
|
|
617
617
|
|
|
618
618
|
|
|
619
|
+
USAGE_PROBLEM_TOKENS_LEGACY_SQL = USAGE_PROBLEM_TOKENS_SQL.replace(
|
|
620
|
+
"CREATE OR REPLACE VIEW usage_problem_tokens AS",
|
|
621
|
+
"CREATE OR REPLACE VIEW usage_problem_tokens_legacy AS",
|
|
622
|
+
)
|
|
623
|
+
USAGE_PROBLEM_READ_ROI_LEGACY_SQL = (
|
|
624
|
+
USAGE_PROBLEM_READ_ROI_SQL.replace(
|
|
625
|
+
"CREATE OR REPLACE VIEW usage_problem_read_roi AS",
|
|
626
|
+
"CREATE OR REPLACE VIEW usage_problem_read_roi_legacy AS",
|
|
627
|
+
)
|
|
628
|
+
.replace("FROM usage_problem_tokens upt", "FROM usage_problem_tokens_legacy upt")
|
|
629
|
+
)
|
|
630
|
+
USAGE_READ_BEFORE_SOLVE_ROI_LEGACY_SQL = (
|
|
631
|
+
USAGE_READ_BEFORE_SOLVE_ROI_SQL.replace(
|
|
632
|
+
"CREATE OR REPLACE VIEW usage_read_before_solve_roi AS",
|
|
633
|
+
"CREATE OR REPLACE VIEW usage_read_before_solve_roi_legacy AS",
|
|
634
|
+
)
|
|
635
|
+
.replace("FROM usage_problem_read_roi", "FROM usage_problem_read_roi_legacy")
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
USAGE_PROBLEM_RUN_TOKENS_SQL = """
|
|
640
|
+
CREATE OR REPLACE VIEW usage_problem_run_tokens AS
|
|
641
|
+
WITH session_quality AS (
|
|
642
|
+
SELECT
|
|
643
|
+
repo_id,
|
|
644
|
+
host_app,
|
|
645
|
+
host_session_key,
|
|
646
|
+
BOOL_OR(capture_quality = 'exact') AS has_exact_rows,
|
|
647
|
+
BOOL_OR(
|
|
648
|
+
capture_quality = 'exact'
|
|
649
|
+
AND (
|
|
650
|
+
COALESCE(input_tokens, 0) > 0
|
|
651
|
+
OR COALESCE(output_tokens, 0) > 0
|
|
652
|
+
OR COALESCE(cached_input_tokens_total, 0) > 0
|
|
653
|
+
OR COALESCE(reasoning_output_tokens, 0) > 0
|
|
654
|
+
)
|
|
655
|
+
) AS has_nonzero_exact_rows,
|
|
656
|
+
BOOL_OR(capture_quality = 'estimated') AS has_estimated_rows
|
|
657
|
+
FROM model_usage
|
|
658
|
+
GROUP BY repo_id, host_app, host_session_key
|
|
659
|
+
),
|
|
660
|
+
preferred_rows AS (
|
|
661
|
+
SELECT mu.*
|
|
662
|
+
FROM model_usage mu
|
|
663
|
+
JOIN session_quality sq
|
|
664
|
+
ON sq.repo_id = mu.repo_id
|
|
665
|
+
AND sq.host_app = mu.host_app
|
|
666
|
+
AND sq.host_session_key = mu.host_session_key
|
|
667
|
+
WHERE (
|
|
668
|
+
sq.has_nonzero_exact_rows
|
|
669
|
+
AND mu.capture_quality = 'exact'
|
|
670
|
+
) OR (
|
|
671
|
+
NOT sq.has_nonzero_exact_rows
|
|
672
|
+
AND mu.capture_quality = 'estimated'
|
|
673
|
+
) OR (
|
|
674
|
+
NOT sq.has_nonzero_exact_rows
|
|
675
|
+
AND NOT sq.has_estimated_rows
|
|
676
|
+
AND sq.has_exact_rows
|
|
677
|
+
AND mu.capture_quality = 'exact'
|
|
678
|
+
)
|
|
679
|
+
),
|
|
680
|
+
eligible_runs AS (
|
|
681
|
+
SELECT *
|
|
682
|
+
FROM problem_runs
|
|
683
|
+
WHERE status IN ('closed', 'abandoned')
|
|
684
|
+
AND closed_at IS NOT NULL
|
|
685
|
+
),
|
|
686
|
+
run_usage AS (
|
|
687
|
+
SELECT
|
|
688
|
+
prun.id AS problem_run_id,
|
|
689
|
+
COUNT(mu.id)::INTEGER AS usage_row_count,
|
|
690
|
+
COUNT(mu.id) FILTER (WHERE mu.capture_quality = 'exact')::INTEGER AS exact_usage_row_count,
|
|
691
|
+
COUNT(mu.id) FILTER (WHERE mu.capture_quality = 'estimated')::INTEGER AS estimated_usage_row_count,
|
|
692
|
+
COALESCE(SUM(mu.input_tokens), 0)::BIGINT AS input_tokens,
|
|
693
|
+
COALESCE(SUM(mu.output_tokens), 0)::BIGINT AS output_tokens,
|
|
694
|
+
COALESCE(SUM(mu.reasoning_output_tokens), 0)::BIGINT AS reasoning_output_tokens,
|
|
695
|
+
COALESCE(SUM(mu.cached_input_tokens_total), 0)::BIGINT AS cached_input_tokens_total,
|
|
696
|
+
COALESCE(SUM(mu.cache_read_input_tokens), 0)::BIGINT AS cache_read_input_tokens,
|
|
697
|
+
COALESCE(SUM(mu.cache_creation_input_tokens), 0)::BIGINT AS cache_creation_input_tokens,
|
|
698
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role IN ('foreground', 'worker')), 0)::BIGINT AS foreground_worker_input_tokens,
|
|
699
|
+
COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role IN ('foreground', 'worker')), 0)::BIGINT AS foreground_worker_output_tokens,
|
|
700
|
+
(
|
|
701
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role IN ('foreground', 'worker')), 0)
|
|
702
|
+
+ COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role IN ('foreground', 'worker')), 0)
|
|
703
|
+
)::BIGINT AS foreground_worker_fresh_work_tokens,
|
|
704
|
+
(
|
|
705
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role IN ('foreground', 'worker')), 0)
|
|
706
|
+
+ COALESCE(SUM(mu.cached_input_tokens_total) FILTER (WHERE mu.agent_role IN ('foreground', 'worker')), 0)
|
|
707
|
+
+ COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role IN ('foreground', 'worker')), 0)
|
|
708
|
+
)::BIGINT AS foreground_worker_all_tokens_including_cache,
|
|
709
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role = 'librarian'), 0)::BIGINT AS librarian_input_tokens,
|
|
710
|
+
COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role = 'librarian'), 0)::BIGINT AS librarian_output_tokens,
|
|
711
|
+
(
|
|
712
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role = 'librarian'), 0)
|
|
713
|
+
+ COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role = 'librarian'), 0)
|
|
714
|
+
)::BIGINT AS librarian_fresh_work_tokens,
|
|
715
|
+
(
|
|
716
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role = 'librarian'), 0)
|
|
717
|
+
+ COALESCE(SUM(mu.cached_input_tokens_total) FILTER (WHERE mu.agent_role = 'librarian'), 0)
|
|
718
|
+
+ COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role = 'librarian'), 0)
|
|
719
|
+
)::BIGINT AS librarian_all_tokens_including_cache,
|
|
720
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role NOT IN ('foreground', 'worker', 'librarian')), 0)::BIGINT AS other_role_input_tokens,
|
|
721
|
+
COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role NOT IN ('foreground', 'worker', 'librarian')), 0)::BIGINT AS other_role_output_tokens,
|
|
722
|
+
(
|
|
723
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role NOT IN ('foreground', 'worker', 'librarian')), 0)
|
|
724
|
+
+ COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role NOT IN ('foreground', 'worker', 'librarian')), 0)
|
|
725
|
+
)::BIGINT AS other_role_fresh_work_tokens,
|
|
726
|
+
(
|
|
727
|
+
COALESCE(SUM(mu.input_tokens) FILTER (WHERE mu.agent_role NOT IN ('foreground', 'worker', 'librarian')), 0)
|
|
728
|
+
+ COALESCE(SUM(mu.cached_input_tokens_total) FILTER (WHERE mu.agent_role NOT IN ('foreground', 'worker', 'librarian')), 0)
|
|
729
|
+
+ COALESCE(SUM(mu.output_tokens) FILTER (WHERE mu.agent_role NOT IN ('foreground', 'worker', 'librarian')), 0)
|
|
730
|
+
)::BIGINT AS other_role_all_tokens_including_cache
|
|
731
|
+
FROM eligible_runs prun
|
|
732
|
+
LEFT JOIN preferred_rows mu
|
|
733
|
+
ON mu.repo_id = prun.repo_id
|
|
734
|
+
AND mu.occurred_at >= prun.opened_at
|
|
735
|
+
AND mu.occurred_at <= prun.closed_at
|
|
736
|
+
AND (
|
|
737
|
+
(
|
|
738
|
+
prun.host_app IS NOT NULL
|
|
739
|
+
AND prun.host_session_key IS NOT NULL
|
|
740
|
+
AND mu.host_app = prun.host_app
|
|
741
|
+
AND mu.host_session_key = prun.host_session_key
|
|
742
|
+
)
|
|
743
|
+
OR (
|
|
744
|
+
(prun.host_app IS NULL OR prun.host_session_key IS NULL)
|
|
745
|
+
AND prun.thread_id IS NOT NULL
|
|
746
|
+
AND mu.thread_id = prun.thread_id
|
|
747
|
+
)
|
|
748
|
+
)
|
|
749
|
+
GROUP BY prun.id
|
|
750
|
+
),
|
|
751
|
+
run_reads AS (
|
|
752
|
+
SELECT
|
|
753
|
+
prun.id AS problem_run_id,
|
|
754
|
+
COUNT(oi.id)::INTEGER AS shellbrain_read_count,
|
|
755
|
+
COALESCE(SUM(ris.pack_token_estimate), 0)::BIGINT AS shellbrain_pack_tokens,
|
|
756
|
+
COALESCE(SUM(ris.concept_token_estimate), 0)::BIGINT AS shellbrain_concept_tokens
|
|
757
|
+
FROM eligible_runs prun
|
|
758
|
+
LEFT JOIN operation_invocations oi
|
|
759
|
+
ON oi.repo_id = prun.repo_id
|
|
760
|
+
AND oi.command = 'read'
|
|
761
|
+
AND oi.outcome = 'ok'
|
|
762
|
+
AND oi.created_at >= prun.opened_at
|
|
763
|
+
AND oi.created_at <= prun.closed_at
|
|
764
|
+
AND (
|
|
765
|
+
(
|
|
766
|
+
prun.host_app IS NOT NULL
|
|
767
|
+
AND prun.host_session_key IS NOT NULL
|
|
768
|
+
AND oi.selected_host_app = prun.host_app
|
|
769
|
+
AND oi.selected_host_session_key = prun.host_session_key
|
|
770
|
+
)
|
|
771
|
+
OR (
|
|
772
|
+
(prun.host_app IS NULL OR prun.host_session_key IS NULL)
|
|
773
|
+
AND prun.thread_id IS NOT NULL
|
|
774
|
+
AND oi.selected_thread_id = prun.thread_id
|
|
775
|
+
)
|
|
776
|
+
)
|
|
777
|
+
LEFT JOIN read_invocation_summaries ris ON ris.invocation_id = oi.id
|
|
778
|
+
GROUP BY prun.id
|
|
779
|
+
)
|
|
780
|
+
SELECT
|
|
781
|
+
prun.id AS problem_run_id,
|
|
782
|
+
prun.repo_id,
|
|
783
|
+
prun.thread_id,
|
|
784
|
+
prun.host_app,
|
|
785
|
+
prun.host_session_key,
|
|
786
|
+
prun.status,
|
|
787
|
+
prun.opened_at,
|
|
788
|
+
prun.closed_at,
|
|
789
|
+
EXTRACT(EPOCH FROM (prun.closed_at - prun.opened_at))::DOUBLE PRECISION AS duration_seconds,
|
|
790
|
+
prun.problem_memory_id,
|
|
791
|
+
prun.solution_memory_id,
|
|
792
|
+
ru.usage_row_count,
|
|
793
|
+
ru.exact_usage_row_count,
|
|
794
|
+
ru.estimated_usage_row_count,
|
|
795
|
+
ru.input_tokens,
|
|
796
|
+
ru.output_tokens,
|
|
797
|
+
ru.reasoning_output_tokens,
|
|
798
|
+
ru.cached_input_tokens_total,
|
|
799
|
+
ru.cache_read_input_tokens,
|
|
800
|
+
ru.cache_creation_input_tokens,
|
|
801
|
+
(
|
|
802
|
+
ru.input_tokens
|
|
803
|
+
+ ru.output_tokens
|
|
804
|
+
)::BIGINT AS fresh_work_tokens,
|
|
805
|
+
(
|
|
806
|
+
ru.input_tokens
|
|
807
|
+
+ ru.cached_input_tokens_total
|
|
808
|
+
+ ru.output_tokens
|
|
809
|
+
)::BIGINT AS all_tokens_including_cache,
|
|
810
|
+
ru.foreground_worker_input_tokens,
|
|
811
|
+
ru.foreground_worker_output_tokens,
|
|
812
|
+
ru.foreground_worker_fresh_work_tokens,
|
|
813
|
+
ru.foreground_worker_all_tokens_including_cache,
|
|
814
|
+
ru.librarian_input_tokens,
|
|
815
|
+
ru.librarian_output_tokens,
|
|
816
|
+
ru.librarian_fresh_work_tokens,
|
|
817
|
+
ru.librarian_all_tokens_including_cache,
|
|
818
|
+
ru.other_role_input_tokens,
|
|
819
|
+
ru.other_role_output_tokens,
|
|
820
|
+
ru.other_role_fresh_work_tokens,
|
|
821
|
+
ru.other_role_all_tokens_including_cache,
|
|
822
|
+
rr.shellbrain_read_count,
|
|
823
|
+
rr.shellbrain_pack_tokens,
|
|
824
|
+
rr.shellbrain_concept_tokens
|
|
825
|
+
FROM eligible_runs prun
|
|
826
|
+
JOIN run_usage ru ON ru.problem_run_id = prun.id
|
|
827
|
+
JOIN run_reads rr ON rr.problem_run_id = prun.id;
|
|
828
|
+
"""
|
|
829
|
+
|
|
830
|
+
|
|
619
831
|
USAGE_TOKEN_CAPTURE_HEALTH_SQL = """
|
|
620
832
|
CREATE OR REPLACE VIEW usage_token_capture_health AS
|
|
621
833
|
WITH synced_sessions AS (
|