agent-notes 2.15.1__tar.gz → 2.16.0__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.
- {agent_notes-2.15.1 → agent_notes-2.16.0}/PKG-INFO +1 -2
- {agent_notes-2.15.1 → agent_notes-2.16.0}/README.md +0 -1
- agent_notes-2.16.0/agent_notes/VERSION +1 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/cli.py +0 -18
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/__init__.py +1 -2
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/doctor.py +40 -5
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/wizard.py +23 -17
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/config.py +43 -53
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/hooks/session-context.md.tpl +1 -1
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/doctor_checks.py +8 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/state.py +1 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/scripts/cost_report.py +2 -2
- agent_notes-2.16.0/agent_notes/services/counts.py +67 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/diagnostics/_checks.py +33 -49
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/diagnostics/_display.py +11 -42
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/install_state_builder.py +2 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/installer.py +4 -1
- agent_notes-2.16.0/agent_notes/services/session_context.py +36 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/state_store.py +2 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes.egg-info/PKG-INFO +1 -2
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes.egg-info/SOURCES.txt +3 -2
- agent_notes-2.16.0/tests/functional/commands/test_doctor_command.py +404 -0
- agent_notes-2.16.0/tests/unit/services/test_session_context.py +132 -0
- agent_notes-2.16.0/tests/unit/test_import_health.py +260 -0
- agent_notes-2.15.1/agent_notes/VERSION +0 -1
- agent_notes-2.15.1/agent_notes/commands/update.py +0 -169
- agent_notes-2.15.1/agent_notes/services/session_context.py +0 -23
- agent_notes-2.15.1/tests/functional/commands/test_doctor_command.py +0 -150
- agent_notes-2.15.1/tests/functional/commands/test_update_command.py +0 -110
- {agent_notes-2.15.1 → agent_notes-2.16.0}/LICENSE +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/__main__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/_install_helpers.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/build.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/config.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/info.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/install.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/list.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/memory.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/regenerate.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/set_role.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/uninstall.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/commands/validate.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/agents.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/analyst.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/api-reviewer.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/architect.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/coder.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/database-specialist.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/debugger.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/devil.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/devops.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/explorer.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/integrations.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/lead.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/performance-profiler.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/refactorer.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/reviewer.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/security-auditor.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/shared/cost_reporting.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/shared/phase0.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/system-auditor.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/tech-writer.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/test-runner.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/agents/test-writer.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/cli/claude.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/cli/copilot.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/cli/opencode.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/commands/brainstorm.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/commands/debug.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/commands/review.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/global-claude.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/global-copilot.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/global-opencode.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-haiku-4-5.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-opus-4-1.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-opus-4-5.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-opus-4-6.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-opus-4-7.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-sonnet-4-5.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-sonnet-4-6.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/models/claude-sonnet-4.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/plugin/claude.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/plugin/opencode-index.js.template +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/plugin/opencode.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/pricing.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/roles/orchestrator.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/roles/reasoner.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/roles/scout.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/roles/worker.yaml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/rules/code-quality.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/rules/safety.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/brainstorming/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/caveman/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/code-review/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/debugging-protocol/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/docker-compose/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/docker-compose-advanced/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/docker-dockerfile/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/docker-dockerfile-languages/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/git/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/grill-me/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/grill-with-docs/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/improve-codebase-architecture/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/obsidian-memory/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-active-storage/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-broadcasting/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-concerns/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-controllers/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-controllers-advanced/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-helpers/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-initializers/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-javascript/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-jobs/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-kamal/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-lib/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-mailers/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-migrations/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-models/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-models-advanced/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-routes/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-style/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-testing-controllers/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-testing-models/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-testing-system/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-validations/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-view-components/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-view-components-advanced/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-views/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/rails-views-advanced/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/refactoring-protocol/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/setup-project-context/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/tdd/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/skills/zoom-out/SKILL.md +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/__pycache__/__init__.cpython-314.pyc +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/frontmatter/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/frontmatter/__pycache__/__init__.cpython-314.pyc +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/frontmatter/__pycache__/claude.cpython-314.pyc +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/frontmatter/__pycache__/opencode.cpython-314.pyc +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/frontmatter/claude.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/data/templates/frontmatter/opencode.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/agent.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/cli_backend.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/diagnostics.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/diff.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/model.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/role.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/rule.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/domain/skill.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/install_state.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/_base.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/agent_registry.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/cli_registry.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/model_registry.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/role_registry.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/rule_registry.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/registries/skill_registry.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/scripts/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/scripts/_claude_backend.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/scripts/_formatting.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/scripts/_opencode_backend.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/scripts/_pricing.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/credentials.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/diagnostics/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/diagnostics/_fix.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/diff.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/fs.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/memory_backend.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/rendering.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/settings_writer.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/ui.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/user_config.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/validation.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/services/wiki_backend.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes/state.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes.egg-info/dependency_links.txt +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes.egg-info/entry_points.txt +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes.egg-info/requires.txt +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/agent_notes.egg-info/top_level.txt +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/pyproject.toml +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/setup.cfg +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/conftest.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/test_config_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/test_info_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/test_install_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/test_list_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/test_regenerate_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/test_uninstall_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/commands/test_validate_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/memory/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/memory/test_memory_command.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/scripts/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/functional/scripts/test_release_script.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/integration/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/integration/build_output/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/integration/build_output/test_build_output.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/integration/install/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/integration/install/test_install_methods.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/integration/plugin_builders/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/integration/plugin_builders/test_plugin_builders.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/plugins/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/plugins/claude/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/plugins/claude/test_agents.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/plugins/test_skills.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/commands/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/commands/test_cost_report_subcommand.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/commands/test_count_agents.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/commands/test_memory_migrate.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/commands/test_wizard_orchestrator_skip.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/commands/test_wizard_preflight.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/registries/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/registries/test_registries.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/scripts/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/scripts/test_cost_report.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/scripts/test_cost_report_scoping.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/scripts/test_formatting_tty.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/scripts/test_time_aggregation.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/__init__.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_build_functions.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_credentials.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_fs.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_installer_plan.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_memory_backend.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_memory_backend_io.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_rendering_includes.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_settings_writer.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/services/test_wiki_backend.py +0 -0
- {agent_notes-2.15.1 → agent_notes-2.16.0}/tests/unit/test_memory_dir_for_backend.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-notes
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.16.0
|
|
4
4
|
Summary: AI agent configuration manager for Claude Code, OpenCode, and Copilot
|
|
5
5
|
Author-email: Eugene Naumov <min.verkligheten@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -115,7 +115,6 @@ agent-notes <command> [options]
|
|
|
115
115
|
|---------|-------------|
|
|
116
116
|
| `install [--local] [--copy]` | Interactive wizard or direct install |
|
|
117
117
|
| `uninstall [--local]` | Remove installed components |
|
|
118
|
-
| `update` | Pull latest, rebuild, reinstall |
|
|
119
118
|
| `doctor [--local] [--fix]` | Check installation health |
|
|
120
119
|
| `info` | Show status and component counts |
|
|
121
120
|
| `list [clis\|models\|roles\|agents\|skills\|rules\|all]` | List engine components or installed |
|
|
@@ -85,7 +85,6 @@ agent-notes <command> [options]
|
|
|
85
85
|
|---------|-------------|
|
|
86
86
|
| `install [--local] [--copy]` | Interactive wizard or direct install |
|
|
87
87
|
| `uninstall [--local]` | Remove installed components |
|
|
88
|
-
| `update` | Pull latest, rebuild, reinstall |
|
|
89
88
|
| `doctor [--local] [--fix]` | Check installation health |
|
|
90
89
|
| `info` | Show status and component counts |
|
|
91
90
|
| `list [clis\|models\|roles\|agents\|skills\|rules\|all]` | List engine components or installed |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.16.0
|
|
@@ -237,15 +237,6 @@ def main():
|
|
|
237
237
|
p_uninstall = subparsers.add_parser("uninstall", help="Remove installed components")
|
|
238
238
|
p_uninstall.add_argument("--local", action="store_true", help="Remove from current project")
|
|
239
239
|
|
|
240
|
-
# update
|
|
241
|
-
p_update = subparsers.add_parser("update", help="Pull latest, show diff, reinstall")
|
|
242
|
-
p_update.add_argument("--dry-run", action="store_true", help="Show diff only, do not reinstall")
|
|
243
|
-
p_update.add_argument("-y", "--yes", action="store_true", help="Skip confirmation prompt")
|
|
244
|
-
p_update.add_argument("--only", action="append", choices=["agents","skills","rules","commands","config","settings"],
|
|
245
|
-
help="Filter diff to these component types (repeatable)")
|
|
246
|
-
p_update.add_argument("--since", help="Override 'before' commit label (cosmetic only for now)")
|
|
247
|
-
p_update.add_argument("--skip-pull", action="store_true", help="Skip git pull")
|
|
248
|
-
|
|
249
240
|
# doctor
|
|
250
241
|
p_doctor = subparsers.add_parser("doctor", help="Check installation health")
|
|
251
242
|
p_doctor.add_argument("--local", action="store_true", help="Check local installation")
|
|
@@ -325,15 +316,6 @@ def main():
|
|
|
325
316
|
elif args.command == "uninstall":
|
|
326
317
|
from .commands.install import uninstall
|
|
327
318
|
uninstall(local=args.local)
|
|
328
|
-
elif args.command == "update":
|
|
329
|
-
from .commands.update import update
|
|
330
|
-
update(
|
|
331
|
-
dry_run=args.dry_run,
|
|
332
|
-
yes=args.yes,
|
|
333
|
-
only=args.only,
|
|
334
|
-
since=args.since,
|
|
335
|
-
skip_pull=args.skip_pull,
|
|
336
|
-
)
|
|
337
319
|
elif args.command == "doctor":
|
|
338
320
|
from .commands.doctor import doctor
|
|
339
321
|
doctor(local=args.local, fix=args.fix)
|
|
@@ -14,14 +14,13 @@ from . import uninstall
|
|
|
14
14
|
from . import build
|
|
15
15
|
from . import doctor
|
|
16
16
|
from . import validate
|
|
17
|
-
from . import update
|
|
18
17
|
from . import regenerate
|
|
19
18
|
from . import list as list_cmd
|
|
20
19
|
from . import memory as memory_cmd
|
|
21
20
|
|
|
22
21
|
__all__ = [
|
|
23
22
|
"install", "uninstall", "show_info",
|
|
24
|
-
"build", "doctor", "validate",
|
|
23
|
+
"build", "doctor", "validate",
|
|
25
24
|
"regenerate", "set_role", "interactive_install",
|
|
26
25
|
"list_cmd", "memory_cmd",
|
|
27
26
|
]
|
|
@@ -62,25 +62,60 @@ def _check_session_hook(scope: str, issues: list) -> None:
|
|
|
62
62
|
))
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
def check_version_drift(scope: str, issues: list, fix_actions: list) -> None:
|
|
66
|
+
"""Check if the installed package version matches the current running version."""
|
|
67
|
+
from .. import install_state
|
|
68
|
+
from ..config import get_version
|
|
69
|
+
from ..domain.diagnostics import Issue, FixAction
|
|
70
|
+
from ..services.state_store import get_scope
|
|
71
|
+
from pathlib import Path
|
|
72
|
+
|
|
73
|
+
state = install_state.load_current_state()
|
|
74
|
+
if state is None:
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
project_path = Path.cwd() if scope == "local" else None
|
|
78
|
+
scope_state = get_scope(state, scope, project_path)
|
|
79
|
+
if scope_state is None:
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
installed_version = scope_state.installed_version
|
|
83
|
+
if not installed_version:
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
current_version = get_version()
|
|
87
|
+
if installed_version != current_version:
|
|
88
|
+
issues.append(Issue(
|
|
89
|
+
"version_drift",
|
|
90
|
+
"state.json",
|
|
91
|
+
f"Installed with v{installed_version} but running v{current_version}. "
|
|
92
|
+
"Run `agent-notes doctor --fix` or `agent-notes install` to update.",
|
|
93
|
+
))
|
|
94
|
+
fix_actions.append(FixAction("_TRIGGER_INSTALL", "state.json", "reinstall to update"))
|
|
95
|
+
|
|
96
|
+
|
|
65
97
|
def diagnose(scope: str, fix: bool = False) -> bool:
|
|
66
98
|
"""Run all diagnostic checks and optionally apply fixes."""
|
|
67
99
|
from .. import install_state
|
|
68
|
-
|
|
100
|
+
|
|
69
101
|
print_summary(scope)
|
|
70
|
-
|
|
102
|
+
|
|
71
103
|
issues = []
|
|
72
104
|
fix_actions = []
|
|
73
|
-
|
|
105
|
+
|
|
74
106
|
# Run checks
|
|
75
107
|
check_stale_files(scope, issues, fix_actions)
|
|
76
|
-
check_broken_symlinks(scope, issues, fix_actions)
|
|
108
|
+
check_broken_symlinks(scope, issues, fix_actions)
|
|
77
109
|
check_shadowed_files(scope, issues, fix_actions)
|
|
78
110
|
check_missing_files(scope, issues, fix_actions)
|
|
79
111
|
check_content_drift(scope, issues, fix_actions)
|
|
80
|
-
|
|
112
|
+
|
|
81
113
|
# Build freshness check (scope-independent)
|
|
82
114
|
check_build_freshness(issues, fix_actions)
|
|
83
115
|
|
|
116
|
+
# Version drift check
|
|
117
|
+
check_version_drift(scope, issues, fix_actions)
|
|
118
|
+
|
|
84
119
|
# SessionStart hook check (Claude Code only)
|
|
85
120
|
_check_session_hook(scope, issues)
|
|
86
121
|
|
|
@@ -8,6 +8,7 @@ from .build import build
|
|
|
8
8
|
from ._install_helpers import (
|
|
9
9
|
count_agents, count_global, count_skills
|
|
10
10
|
)
|
|
11
|
+
from ..services.counts import count_rules_total as _count_rules_total
|
|
11
12
|
from ..services.fs import place_file, place_dir_contents
|
|
12
13
|
from ..services.ui import (
|
|
13
14
|
_can_interactive, _safe_input, _checkbox_select, _radio_select,
|
|
@@ -79,22 +80,7 @@ def _get_skill_groups() -> Dict[str, List[str]]:
|
|
|
79
80
|
|
|
80
81
|
def _count_rules() -> int:
|
|
81
82
|
"""Count rule files."""
|
|
82
|
-
|
|
83
|
-
import os
|
|
84
|
-
if os.environ.get('_WIZARD_TEST_MODE'):
|
|
85
|
-
if not DIST_RULES_DIR.exists():
|
|
86
|
-
return 0
|
|
87
|
-
return len(list(DIST_RULES_DIR.glob("*.md")))
|
|
88
|
-
else:
|
|
89
|
-
try:
|
|
90
|
-
from ..registries import default_rule_registry
|
|
91
|
-
registry = default_rule_registry()
|
|
92
|
-
return len(registry.all())
|
|
93
|
-
except Exception:
|
|
94
|
-
# Fallback to old behavior if registry fails
|
|
95
|
-
if not DIST_RULES_DIR.exists():
|
|
96
|
-
return 0
|
|
97
|
-
return len(list(DIST_RULES_DIR.glob("*.md")))
|
|
83
|
+
return _count_rules_total()
|
|
98
84
|
|
|
99
85
|
|
|
100
86
|
def _select_cli(step: int = 0, total: int = 0, version: str = '') -> Set[str]:
|
|
@@ -629,7 +615,27 @@ def _interactive_install() -> None:
|
|
|
629
615
|
print(f"{Color.RED}Build failed: {e}{Color.NC}")
|
|
630
616
|
return
|
|
631
617
|
|
|
632
|
-
|
|
618
|
+
_execute_install(
|
|
619
|
+
clis=clis,
|
|
620
|
+
scope=scope,
|
|
621
|
+
copy_mode=copy_mode,
|
|
622
|
+
selected_skills=selected_skills,
|
|
623
|
+
role_models=role_models,
|
|
624
|
+
memory_backend=memory_backend,
|
|
625
|
+
memory_path=memory_path,
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def _execute_install(
|
|
630
|
+
clis: Set[str],
|
|
631
|
+
scope: str,
|
|
632
|
+
copy_mode: bool,
|
|
633
|
+
selected_skills: List[str],
|
|
634
|
+
role_models: Dict[str, Dict[str, str]],
|
|
635
|
+
memory_backend: str,
|
|
636
|
+
memory_path: str,
|
|
637
|
+
) -> None:
|
|
638
|
+
"""Run all installation steps after parameters have been collected and the build is done."""
|
|
633
639
|
print(f"\nInstalling ({scope}, {'copy' if copy_mode else 'symlink'}) ...\n")
|
|
634
640
|
|
|
635
641
|
from ..services import fs as _fs
|
|
@@ -91,56 +91,46 @@ def global_output_path(backend) -> Optional[Path]:
|
|
|
91
91
|
return dist_dir_for(backend) / backend.layout["config"]
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
# === Backward compatibility
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
CLAUDE_HOME = _lazy_backend_attr('claude', _fb_home)()
|
|
139
|
-
OPENCODE_HOME = _lazy_backend_attr('opencode', _fb_home)()
|
|
140
|
-
GITHUB_HOME = _lazy_backend_attr('copilot', _fb_home)()
|
|
141
|
-
DIST_CLAUDE_DIR = _lazy_backend_attr('claude', _fb_dist)()
|
|
142
|
-
DIST_OPENCODE_DIR = _lazy_backend_attr('opencode', _fb_dist)()
|
|
143
|
-
DIST_GITHUB_DIR = _lazy_backend_attr('copilot', _fb_dist)()
|
|
144
|
-
GLOBAL_CLAUDE_MD = _lazy_backend_attr('claude', _fb_template)()
|
|
145
|
-
GLOBAL_OPENCODE_MD = _lazy_backend_attr('opencode', _fb_template)()
|
|
146
|
-
GLOBAL_COPILOT_MD = _lazy_backend_attr('copilot', _fb_template)()
|
|
94
|
+
# === Backward compatibility constants ===
|
|
95
|
+
# Hardcoded fallbacks match the shipped YAMLs and protect against circular
|
|
96
|
+
# imports if this module is ever imported very early in the load sequence.
|
|
97
|
+
_FALLBACKS = {
|
|
98
|
+
'claude': {'home': Path.home() / ".claude", 'template': "global-claude.md", 'dist': "claude"},
|
|
99
|
+
'opencode': {'home': Path.home() / ".config" / "opencode", 'template': "global-opencode.md", 'dist': "opencode"},
|
|
100
|
+
'copilot': {'home': Path.home() / ".github", 'template': "global-copilot.md", 'dist': "github"},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _backend_home(name: str) -> Path:
|
|
105
|
+
try:
|
|
106
|
+
from .registries.cli_registry import default_registry
|
|
107
|
+
return default_registry().get(name).global_home
|
|
108
|
+
except (ImportError, KeyError):
|
|
109
|
+
return _FALLBACKS[name]['home']
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _backend_dist(name: str) -> Path:
|
|
113
|
+
try:
|
|
114
|
+
from .registries.cli_registry import default_registry
|
|
115
|
+
return dist_dir_for(default_registry().get(name))
|
|
116
|
+
except (ImportError, KeyError):
|
|
117
|
+
return DIST_DIR / _FALLBACKS[name]['dist']
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _backend_template(name: str) -> Path:
|
|
121
|
+
try:
|
|
122
|
+
from .registries.cli_registry import default_registry
|
|
123
|
+
return global_template_path(default_registry().get(name))
|
|
124
|
+
except (ImportError, KeyError):
|
|
125
|
+
return DATA_DIR / _FALLBACKS[name]['template']
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
CLAUDE_HOME = _backend_home('claude')
|
|
129
|
+
OPENCODE_HOME = _backend_home('opencode')
|
|
130
|
+
GITHUB_HOME = _backend_home('copilot')
|
|
131
|
+
DIST_CLAUDE_DIR = _backend_dist('claude')
|
|
132
|
+
DIST_OPENCODE_DIR = _backend_dist('opencode')
|
|
133
|
+
DIST_GITHUB_DIR = _backend_dist('copilot')
|
|
134
|
+
GLOBAL_CLAUDE_MD = _backend_template('claude')
|
|
135
|
+
GLOBAL_OPENCODE_MD = _backend_template('opencode')
|
|
136
|
+
GLOBAL_COPILOT_MD = _backend_template('copilot')
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"""Scoped health checks for agent-notes — only touches files we own."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"expected_paths_for_install",
|
|
7
|
+
"check_missing",
|
|
8
|
+
"check_broken",
|
|
9
|
+
"check_drift",
|
|
10
|
+
"check_stale",
|
|
11
|
+
]
|
|
4
12
|
from pathlib import Path
|
|
5
13
|
from typing import Optional
|
|
6
14
|
|
|
@@ -5,6 +5,7 @@ from datetime import datetime, timezone
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from . import _claude_backend, _opencode_backend
|
|
8
|
+
from ._opencode_backend import DB as _OPENCODE_DB
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def _opencode_active() -> bool:
|
|
@@ -21,8 +22,7 @@ def _by_recency(since: float | None = None, session_id: str | None = None) -> in
|
|
|
21
22
|
if jsonls:
|
|
22
23
|
claude_mtime = max(f.stat().st_mtime for f in jsonls)
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
opencode_mtime = opencode_db.stat().st_mtime if opencode_db.exists() else 0.0
|
|
25
|
+
opencode_mtime = _OPENCODE_DB.stat().st_mtime if _OPENCODE_DB.exists() else 0.0
|
|
26
26
|
|
|
27
27
|
if claude_mtime == 0.0 and opencode_mtime == 0.0:
|
|
28
28
|
print("No session data found (no Claude Code transcripts or OpenCode database).")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Shared counting helpers for installed components."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def count_rules_total() -> int:
|
|
7
|
+
"""Count total available rule files (for wizard display).
|
|
8
|
+
|
|
9
|
+
Uses the rule registry when available; falls back to counting .md files
|
|
10
|
+
directly from the dist rules directory.
|
|
11
|
+
"""
|
|
12
|
+
from ..config import DIST_RULES_DIR
|
|
13
|
+
|
|
14
|
+
if os.environ.get('_WIZARD_TEST_MODE'):
|
|
15
|
+
if not DIST_RULES_DIR.exists():
|
|
16
|
+
return 0
|
|
17
|
+
return len(list(DIST_RULES_DIR.glob("*.md")))
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from ..registries import default_rule_registry
|
|
21
|
+
registry = default_rule_registry()
|
|
22
|
+
return len(registry.all())
|
|
23
|
+
except Exception:
|
|
24
|
+
if not DIST_RULES_DIR.exists():
|
|
25
|
+
return 0
|
|
26
|
+
return len(list(DIST_RULES_DIR.glob("*.md")))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def count_skills(backend, scope: str) -> tuple:
|
|
30
|
+
"""Count (installed, expected) skills for a CLI backend. Excludes broken symlinks."""
|
|
31
|
+
from . import installer
|
|
32
|
+
from ..config import DIST_SKILLS_DIR
|
|
33
|
+
|
|
34
|
+
if not backend.supports("skills"):
|
|
35
|
+
return 0, 0
|
|
36
|
+
|
|
37
|
+
skills_dir = installer.target_dir_for(backend, "skills", scope)
|
|
38
|
+
if skills_dir and skills_dir.exists():
|
|
39
|
+
installed = len([d for d in skills_dir.iterdir() if d.is_dir() and d.exists()])
|
|
40
|
+
else:
|
|
41
|
+
installed = 0
|
|
42
|
+
|
|
43
|
+
expected = (
|
|
44
|
+
len([d for d in DIST_SKILLS_DIR.iterdir() if d.is_dir()])
|
|
45
|
+
if DIST_SKILLS_DIR and DIST_SKILLS_DIR.exists()
|
|
46
|
+
else 0
|
|
47
|
+
)
|
|
48
|
+
return installed, expected
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def count_rules(backend, scope: str) -> tuple:
|
|
52
|
+
"""Count (installed, expected) rules for a CLI backend."""
|
|
53
|
+
from . import installer
|
|
54
|
+
from ..config import DIST_RULES_DIR
|
|
55
|
+
|
|
56
|
+
if not backend.supports("rules"):
|
|
57
|
+
return 0, 0
|
|
58
|
+
|
|
59
|
+
rules_dir = installer.target_dir_for(backend, "rules", scope)
|
|
60
|
+
installed = len(list(rules_dir.glob("*.md"))) if rules_dir and rules_dir.exists() else 0
|
|
61
|
+
|
|
62
|
+
expected = (
|
|
63
|
+
len(list(DIST_RULES_DIR.glob("*.md")))
|
|
64
|
+
if DIST_RULES_DIR and DIST_RULES_DIR.exists()
|
|
65
|
+
else 0
|
|
66
|
+
)
|
|
67
|
+
return installed, expected
|
|
@@ -7,20 +7,30 @@ from typing import List, Optional
|
|
|
7
7
|
from ...domain.diagnostics import Issue, FixAction
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
def _load_scope_state(scope: str):
|
|
11
|
+
"""Load registry and scope state for a given scope.
|
|
12
|
+
|
|
13
|
+
Returns (registry, scope_state) where scope_state may be None if no
|
|
14
|
+
state file exists.
|
|
15
|
+
"""
|
|
16
|
+
from ...registries.cli_registry import load_registry
|
|
17
|
+
from ... import install_state
|
|
15
18
|
from ...state import get_scope
|
|
16
19
|
|
|
17
20
|
registry = load_registry()
|
|
18
21
|
state = install_state.load_current_state()
|
|
19
22
|
if state is None:
|
|
20
|
-
|
|
21
|
-
else
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
return registry, None
|
|
24
|
+
project_path = Path.cwd() if scope == "local" else None
|
|
25
|
+
scope_state = get_scope(state, scope, project_path)
|
|
26
|
+
return registry, scope_state
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def check_stale_files(scope: str, issues: List[Issue], fix_actions: List[FixAction]):
|
|
30
|
+
"""Check for installed files without matching source - DELEGATED to doctor_checks."""
|
|
31
|
+
from ... import doctor_checks
|
|
32
|
+
|
|
33
|
+
registry, scope_state = _load_scope_state(scope)
|
|
24
34
|
doctor_checks.check_stale(scope, scope_state, registry, issues, fix_actions)
|
|
25
35
|
|
|
26
36
|
|
|
@@ -30,7 +40,7 @@ def _find_dist_source(symlink: Path, scope: str) -> Optional[Path]:
|
|
|
30
40
|
Iterates all registered backends; returns first dist source whose
|
|
31
41
|
component and filename match the given symlink.
|
|
32
42
|
"""
|
|
33
|
-
from ...
|
|
43
|
+
from ...registries.cli_registry import load_registry
|
|
34
44
|
from ... import installer
|
|
35
45
|
registry = load_registry()
|
|
36
46
|
|
|
@@ -75,35 +85,17 @@ def _find_dist_source(symlink: Path, scope: str) -> Optional[Path]:
|
|
|
75
85
|
|
|
76
86
|
def check_broken_symlinks(scope: str, issues: List[Issue], fix_actions: List[FixAction]):
|
|
77
87
|
"""Check for symlinks with non-existent targets - DELEGATED to doctor_checks."""
|
|
78
|
-
|
|
79
|
-
from ...cli_backend import load_registry
|
|
80
|
-
from ... import install_state, doctor_checks
|
|
81
|
-
from ...state import get_scope
|
|
88
|
+
from ... import doctor_checks
|
|
82
89
|
|
|
83
|
-
registry =
|
|
84
|
-
state = install_state.load_current_state()
|
|
85
|
-
if state is None:
|
|
86
|
-
scope_state = None
|
|
87
|
-
else:
|
|
88
|
-
project_path = Path.cwd() if scope == "local" else None
|
|
89
|
-
scope_state = get_scope(state, scope, project_path)
|
|
90
|
+
registry, scope_state = _load_scope_state(scope)
|
|
90
91
|
doctor_checks.check_broken(scope, registry, issues, fix_actions, scope_state)
|
|
91
92
|
|
|
92
93
|
|
|
93
94
|
def check_shadowed_files(scope: str, issues: List[Issue], fix_actions: List[FixAction]):
|
|
94
95
|
"""Check for regular files where symlinks are expected - TARGETED check only."""
|
|
95
|
-
from ...
|
|
96
|
-
from ... import install_state, doctor_checks
|
|
97
|
-
from ...state import get_scope
|
|
96
|
+
from ... import doctor_checks
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
registry = load_registry()
|
|
101
|
-
state = install_state.load_current_state()
|
|
102
|
-
if state is None:
|
|
103
|
-
scope_state = None
|
|
104
|
-
else:
|
|
105
|
-
project_path = Path.cwd() if scope == "local" else None
|
|
106
|
-
scope_state = get_scope(state, scope, project_path)
|
|
98
|
+
registry, scope_state = _load_scope_state(scope)
|
|
107
99
|
|
|
108
100
|
# Only check paths we know should exist
|
|
109
101
|
for src, dst, backend_name, component in doctor_checks.expected_paths_for_install(registry, scope):
|
|
@@ -119,13 +111,14 @@ def check_shadowed_files(scope: str, issues: List[Issue], fix_actions: List[FixA
|
|
|
119
111
|
|
|
120
112
|
def check_missing_files(scope: str, issues: List[Issue], fix_actions: List[FixAction]):
|
|
121
113
|
"""Check for source files that aren't installed - DELEGATED to doctor_checks."""
|
|
122
|
-
|
|
123
|
-
from ...
|
|
124
|
-
from ... import
|
|
114
|
+
from ... import doctor_checks
|
|
115
|
+
from ...registries.cli_registry import load_registry
|
|
116
|
+
from ... import install_state
|
|
125
117
|
from ...state import get_scope
|
|
126
118
|
|
|
127
119
|
registry = load_registry()
|
|
128
120
|
# Pass scope state so opted-out backends aren't flagged as "missing".
|
|
121
|
+
# Use a try/except here since local scope resolution can raise ValueError/KeyError.
|
|
129
122
|
state = install_state.load_current_state()
|
|
130
123
|
scope_state = None
|
|
131
124
|
if state is not None:
|
|
@@ -144,18 +137,9 @@ def check_missing_files(scope: str, issues: List[Issue], fix_actions: List[FixAc
|
|
|
144
137
|
|
|
145
138
|
def check_content_drift(scope: str, issues: List[Issue], fix_actions: List[FixAction]):
|
|
146
139
|
"""Check for copied files that differ from source - DELEGATED to doctor_checks."""
|
|
147
|
-
|
|
148
|
-
from ...cli_backend import load_registry
|
|
149
|
-
from ... import install_state, doctor_checks
|
|
150
|
-
from ...state import get_scope
|
|
140
|
+
from ... import doctor_checks
|
|
151
141
|
|
|
152
|
-
registry =
|
|
153
|
-
state = install_state.load_current_state()
|
|
154
|
-
if state is None:
|
|
155
|
-
scope_state = None
|
|
156
|
-
else:
|
|
157
|
-
project_path = Path.cwd() if scope == "local" else None
|
|
158
|
-
scope_state = get_scope(state, scope, project_path)
|
|
142
|
+
registry, scope_state = _load_scope_state(scope)
|
|
159
143
|
doctor_checks.check_drift(scope, registry, issues, fix_actions, scope_state)
|
|
160
144
|
|
|
161
145
|
|
|
@@ -167,7 +151,7 @@ def check_build_freshness(issues: List[Issue], fix_actions: List[FixAction]):
|
|
|
167
151
|
# Check agents.yaml vs generated agents
|
|
168
152
|
if agents_yaml.exists():
|
|
169
153
|
source_time = agents_yaml.stat().st_mtime
|
|
170
|
-
from ...
|
|
154
|
+
from ...registries.cli_registry import load_registry
|
|
171
155
|
from ...config import dist_dir_for
|
|
172
156
|
|
|
173
157
|
registry = load_registry()
|
|
@@ -184,7 +168,7 @@ def check_build_freshness(issues: List[Issue], fix_actions: List[FixAction]):
|
|
|
184
168
|
# Check individual source agents
|
|
185
169
|
source_agents_dir = AGENTS_DIR
|
|
186
170
|
if source_agents_dir.exists():
|
|
187
|
-
from ...
|
|
171
|
+
from ...registries.cli_registry import load_registry
|
|
188
172
|
from ...config import dist_dir_for
|
|
189
173
|
|
|
190
174
|
registry = load_registry()
|
|
@@ -202,7 +186,7 @@ def check_build_freshness(issues: List[Issue], fix_actions: List[FixAction]):
|
|
|
202
186
|
fix_actions.append(FixAction("BUILD", str(gen_file), "regenerate from source"))
|
|
203
187
|
|
|
204
188
|
# Check global source files
|
|
205
|
-
from ...
|
|
189
|
+
from ...registries.cli_registry import load_registry
|
|
206
190
|
from ...config import global_template_path, global_output_path
|
|
207
191
|
|
|
208
192
|
registry = load_registry()
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
"""Display and summary functions for agent-notes diagnostics."""
|
|
2
2
|
|
|
3
|
+
__all__ = [
|
|
4
|
+
"count_stale",
|
|
5
|
+
"print_summary",
|
|
6
|
+
"print_issues",
|
|
7
|
+
]
|
|
8
|
+
|
|
3
9
|
from pathlib import Path
|
|
4
10
|
from typing import List, Dict
|
|
5
11
|
|
|
6
12
|
from ...domain.diagnostics import Issue
|
|
13
|
+
from ..counts import count_skills as _count_skills_impl, count_rules as _count_rules_impl
|
|
7
14
|
|
|
8
15
|
|
|
9
16
|
def _cli_base_dir(backend, scope: str) -> Path:
|
|
@@ -34,50 +41,12 @@ def _count_agents(backend, scope: str) -> tuple:
|
|
|
34
41
|
|
|
35
42
|
def _count_skills(backend, scope: str) -> tuple:
|
|
36
43
|
"""Count (installed, expected) skills for a CLI backend. Excludes broken symlinks."""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# Helper to get DIST_SKILLS_DIR
|
|
40
|
-
def _get_dist_skills_dir():
|
|
41
|
-
from ...config import DIST_SKILLS_DIR
|
|
42
|
-
return DIST_SKILLS_DIR
|
|
43
|
-
|
|
44
|
-
if not backend.supports("skills"):
|
|
45
|
-
return 0, 0
|
|
46
|
-
|
|
47
|
-
# Count installed
|
|
48
|
-
skills_dir = installer.target_dir_for(backend, "skills", scope)
|
|
49
|
-
if skills_dir and skills_dir.exists():
|
|
50
|
-
installed = len([d for d in skills_dir.iterdir() if d.is_dir() and d.exists()])
|
|
51
|
-
else:
|
|
52
|
-
installed = 0
|
|
53
|
-
|
|
54
|
-
# Count expected (universal skills)
|
|
55
|
-
dist_skills_dir = _get_dist_skills_dir()
|
|
56
|
-
expected = len([d for d in dist_skills_dir.iterdir() if d.is_dir()]) if dist_skills_dir and dist_skills_dir.exists() else 0
|
|
57
|
-
return installed, expected
|
|
58
|
-
|
|
44
|
+
return _count_skills_impl(backend, scope)
|
|
59
45
|
|
|
60
46
|
|
|
61
47
|
def _count_rules(backend, scope: str) -> tuple:
|
|
62
48
|
"""Count (installed, expected) rules for a CLI backend."""
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
# Helper to get DIST_RULES_DIR
|
|
66
|
-
def _get_dist_rules_dir():
|
|
67
|
-
from ...config import DIST_RULES_DIR
|
|
68
|
-
return DIST_RULES_DIR
|
|
69
|
-
|
|
70
|
-
if not backend.supports("rules"):
|
|
71
|
-
return 0, 0
|
|
72
|
-
|
|
73
|
-
# Count installed
|
|
74
|
-
rules_dir = installer.target_dir_for(backend, "rules", scope)
|
|
75
|
-
installed = len(list(rules_dir.glob("*.md"))) if rules_dir and rules_dir.exists() else 0
|
|
76
|
-
|
|
77
|
-
# Count expected
|
|
78
|
-
dist_rules_dir = _get_dist_rules_dir()
|
|
79
|
-
expected = len(list(dist_rules_dir.glob("*.md"))) if dist_rules_dir and dist_rules_dir.exists() else 0
|
|
80
|
-
return installed, expected
|
|
49
|
+
return _count_rules_impl(backend, scope)
|
|
81
50
|
|
|
82
51
|
|
|
83
52
|
def _check_config(backend, scope: str) -> tuple:
|
|
@@ -101,9 +70,9 @@ def _check_config(backend, scope: str) -> tuple:
|
|
|
101
70
|
|
|
102
71
|
def _check_role_models(state):
|
|
103
72
|
"""Display role→model assignments and check compatibility."""
|
|
104
|
-
from ...model_registry import load_model_registry
|
|
73
|
+
from ...registries.model_registry import load_model_registry
|
|
105
74
|
from ...registries.cli_registry import load_registry
|
|
106
|
-
from ...role_registry import load_role_registry
|
|
75
|
+
from ...registries.role_registry import load_role_registry
|
|
107
76
|
from ...config import Color
|
|
108
77
|
|
|
109
78
|
model_registry = load_model_registry()
|