agent-notes 2.13.0__tar.gz → 2.15.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.13.0 → agent_notes-2.15.0}/PKG-INFO +1 -1
- agent_notes-2.15.0/agent_notes/VERSION +1 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/cli.py +1 -1
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/memory.py +171 -4
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/config.py +2 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/state.py +1 -1
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/memory_backend.py +23 -6
- agent_notes-2.15.0/agent_notes/services/wiki_backend.py +669 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes.egg-info/PKG-INFO +1 -1
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes.egg-info/SOURCES.txt +3 -1
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_memory_backend_io.py +214 -6
- agent_notes-2.15.0/tests/unit/services/test_wiki_backend.py +828 -0
- agent_notes-2.13.0/agent_notes/VERSION +0 -1
- {agent_notes-2.13.0 → agent_notes-2.15.0}/LICENSE +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/README.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/__main__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/_install_helpers.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/build.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/config.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/doctor.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/info.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/install.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/list.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/regenerate.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/set_role.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/uninstall.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/update.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/validate.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/commands/wizard.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/agents.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/analyst.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/api-reviewer.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/architect.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/coder.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/database-specialist.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/debugger.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/devil.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/devops.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/explorer.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/integrations.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/lead.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/performance-profiler.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/refactorer.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/reviewer.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/security-auditor.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/shared/cost_reporting.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/shared/phase0.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/system-auditor.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/tech-writer.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/test-runner.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/agents/test-writer.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/cli/claude.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/cli/copilot.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/cli/opencode.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/commands/brainstorm.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/commands/debug.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/commands/review.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/global-claude.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/global-copilot.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/global-opencode.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/hooks/session-context.md.tpl +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-haiku-4-5.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-opus-4-1.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-opus-4-5.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-opus-4-6.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-opus-4-7.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-sonnet-4-5.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-sonnet-4-6.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/models/claude-sonnet-4.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/plugin/claude.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/plugin/opencode-index.js.template +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/plugin/opencode.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/pricing.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/roles/orchestrator.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/roles/reasoner.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/roles/scout.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/roles/worker.yaml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/rules/code-quality.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/rules/safety.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/brainstorming/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/caveman/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/code-review/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/debugging-protocol/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/docker-compose/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/docker-compose-advanced/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/docker-dockerfile/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/docker-dockerfile-languages/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/git/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/grill-me/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/grill-with-docs/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/improve-codebase-architecture/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/obsidian-memory/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-active-storage/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-broadcasting/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-concerns/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-controllers/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-controllers-advanced/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-helpers/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-initializers/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-javascript/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-jobs/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-kamal/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-lib/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-mailers/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-migrations/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-models/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-models-advanced/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-routes/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-style/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-testing-controllers/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-testing-models/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-testing-system/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-validations/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-view-components/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-view-components-advanced/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-views/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/rails-views-advanced/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/refactoring-protocol/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/setup-project-context/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/tdd/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/skills/zoom-out/SKILL.md +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/__pycache__/__init__.cpython-314.pyc +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/frontmatter/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/frontmatter/__pycache__/__init__.cpython-314.pyc +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/frontmatter/__pycache__/claude.cpython-314.pyc +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/frontmatter/__pycache__/opencode.cpython-314.pyc +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/frontmatter/claude.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/data/templates/frontmatter/opencode.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/doctor_checks.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/agent.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/cli_backend.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/diagnostics.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/diff.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/model.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/role.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/rule.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/domain/skill.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/install_state.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/_base.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/agent_registry.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/cli_registry.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/model_registry.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/role_registry.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/rule_registry.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/registries/skill_registry.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/scripts/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/scripts/_claude_backend.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/scripts/_formatting.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/scripts/_opencode_backend.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/scripts/_pricing.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/scripts/cost_report.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/credentials.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/diagnostics/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/diagnostics/_checks.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/diagnostics/_display.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/diagnostics/_fix.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/diff.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/fs.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/install_state_builder.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/installer.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/rendering.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/session_context.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/settings_writer.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/state_store.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/ui.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/user_config.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/services/validation.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes/state.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes.egg-info/dependency_links.txt +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes.egg-info/entry_points.txt +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes.egg-info/requires.txt +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/agent_notes.egg-info/top_level.txt +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/pyproject.toml +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/setup.cfg +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/conftest.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_config_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_doctor_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_info_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_install_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_list_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_regenerate_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_uninstall_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_update_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/commands/test_validate_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/memory/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/memory/test_memory_command.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/scripts/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/functional/scripts/test_release_script.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/integration/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/integration/build_output/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/integration/build_output/test_build_output.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/integration/install/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/integration/install/test_install_methods.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/integration/plugin_builders/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/integration/plugin_builders/test_plugin_builders.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/plugins/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/plugins/claude/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/plugins/claude/test_agents.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/plugins/test_skills.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/commands/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/commands/test_cost_report_subcommand.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/commands/test_count_agents.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/commands/test_memory_migrate.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/commands/test_wizard_orchestrator_skip.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/commands/test_wizard_preflight.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/registries/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/registries/test_registries.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/scripts/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/scripts/test_cost_report.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/scripts/test_cost_report_scoping.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/scripts/test_formatting_tty.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/scripts/test_time_aggregation.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/__init__.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_build_functions.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_credentials.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_fs.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_installer_plan.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_memory_backend.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_rendering_includes.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/services/test_settings_writer.py +0 -0
- {agent_notes-2.13.0 → agent_notes-2.15.0}/tests/unit/test_memory_dir_for_backend.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.15.0
|
|
@@ -282,7 +282,7 @@ def main():
|
|
|
282
282
|
# memory
|
|
283
283
|
p_memory = subparsers.add_parser("memory", help="Manage agent memory")
|
|
284
284
|
p_memory.add_argument("action", nargs="?", default="list",
|
|
285
|
-
choices=["init", "list", "vault", "index", "add", "size", "show", "reset", "export", "import"],
|
|
285
|
+
choices=["init", "list", "vault", "index", "add", "size", "show", "reset", "export", "import", "ingest", "query", "lint"],
|
|
286
286
|
help="Memory action")
|
|
287
287
|
p_memory.add_argument("name", nargs="?", help="Agent name / note title (for show/reset/add)")
|
|
288
288
|
p_memory.add_argument("extra", nargs="*", help="Additional args (for add: body [type] [agent] [project])")
|
|
@@ -43,6 +43,13 @@ def do_init() -> None:
|
|
|
43
43
|
if path is None:
|
|
44
44
|
print("Memory path not configured.")
|
|
45
45
|
return
|
|
46
|
+
if backend == "wiki":
|
|
47
|
+
from ..services.wiki_backend import wiki_init, WIKI_PAGE_TYPES
|
|
48
|
+
wiki_init(path)
|
|
49
|
+
print(f"{Color.GREEN}Wiki initialised at {path}{Color.NC}")
|
|
50
|
+
print(f" Folders: raw/, wiki/{{{', '.join(WIKI_PAGE_TYPES)}}}")
|
|
51
|
+
print(f" Index: {path / 'wiki' / 'index.md'}")
|
|
52
|
+
return
|
|
46
53
|
if backend == "obsidian":
|
|
47
54
|
from ..services.memory_backend import obsidian_init, OBSIDIAN_CATEGORIES
|
|
48
55
|
obsidian_init(path)
|
|
@@ -65,7 +72,11 @@ def do_index() -> None:
|
|
|
65
72
|
if path is None:
|
|
66
73
|
print("Memory path not configured.")
|
|
67
74
|
return
|
|
68
|
-
if backend == "
|
|
75
|
+
if backend == "wiki":
|
|
76
|
+
from ..services.wiki_backend import wiki_regenerate_index
|
|
77
|
+
wiki_regenerate_index(path)
|
|
78
|
+
print(f"{Color.GREEN}index.md regenerated at {path / 'wiki' / 'index.md'}{Color.NC}")
|
|
79
|
+
elif backend == "obsidian":
|
|
69
80
|
from ..services.memory_backend import obsidian_regenerate_index
|
|
70
81
|
obsidian_regenerate_index(path)
|
|
71
82
|
print(f"{Color.GREEN}Index.md regenerated at {path / 'Index.md'}{Color.NC}")
|
|
@@ -75,8 +86,21 @@ def do_index() -> None:
|
|
|
75
86
|
print(f"{Color.GREEN}Index.md regenerated at {path / 'Index.md'}{Color.NC}")
|
|
76
87
|
|
|
77
88
|
|
|
89
|
+
_WIKI_TYPE_MAP = {
|
|
90
|
+
"pattern": "concepts",
|
|
91
|
+
"decision": "concepts",
|
|
92
|
+
"mistake": "concepts",
|
|
93
|
+
"context": "concepts",
|
|
94
|
+
"concept": "concepts",
|
|
95
|
+
"entity": "entities",
|
|
96
|
+
"synthesis": "synthesis",
|
|
97
|
+
"session": "sessions",
|
|
98
|
+
"source": "sources",
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
78
102
|
def do_add(title: str, body: str, note_type: str = "context", agent: str = "", project: str = "", tags: Optional[list] = None) -> None:
|
|
79
|
-
"""Add a note to memory (obsidian
|
|
103
|
+
"""Add a note to memory (obsidian or wiki backend)."""
|
|
80
104
|
backend, path = _load_memory_config()
|
|
81
105
|
if backend == "none":
|
|
82
106
|
print("Memory is disabled. Run `agent-notes memory vault` to check configuration.")
|
|
@@ -84,7 +108,21 @@ def do_add(title: str, body: str, note_type: str = "context", agent: str = "", p
|
|
|
84
108
|
if path is None:
|
|
85
109
|
print("Memory path not configured.")
|
|
86
110
|
return
|
|
87
|
-
if backend == "
|
|
111
|
+
if backend == "wiki":
|
|
112
|
+
from ..services.wiki_backend import wiki_write_page
|
|
113
|
+
page_type = _WIKI_TYPE_MAP.get(note_type, "concepts")
|
|
114
|
+
extra_tags = [note_type] if note_type not in ("concept", "entity", "synthesis", "session", "source") else []
|
|
115
|
+
page_path = wiki_write_page(
|
|
116
|
+
path,
|
|
117
|
+
title=title,
|
|
118
|
+
body=body,
|
|
119
|
+
page_type=page_type,
|
|
120
|
+
agent=agent,
|
|
121
|
+
project=project,
|
|
122
|
+
tags=(tags or []) + extra_tags,
|
|
123
|
+
)
|
|
124
|
+
print(f"{Color.GREEN}Wiki page saved: {page_path}{Color.NC}")
|
|
125
|
+
elif backend == "obsidian":
|
|
88
126
|
from ..services.memory_backend import obsidian_init, obsidian_write_note
|
|
89
127
|
obsidian_init(path)
|
|
90
128
|
note_path = obsidian_write_note(
|
|
@@ -98,7 +136,7 @@ def do_add(title: str, body: str, note_type: str = "context", agent: str = "", p
|
|
|
98
136
|
)
|
|
99
137
|
print(f"{Color.GREEN}Note saved: {note_path}{Color.NC}")
|
|
100
138
|
else:
|
|
101
|
-
print("The `add` subcommand is for the obsidian backend.")
|
|
139
|
+
print("The `add` subcommand is for the obsidian or wiki backend.")
|
|
102
140
|
print("For local backend, write files directly to the agent subdirectory.")
|
|
103
141
|
|
|
104
142
|
|
|
@@ -110,6 +148,26 @@ def do_list() -> None:
|
|
|
110
148
|
print("Memory is disabled. Run `agent-notes memory backend` to enable it.")
|
|
111
149
|
return
|
|
112
150
|
|
|
151
|
+
if backend == "wiki":
|
|
152
|
+
if path is None or not path.exists():
|
|
153
|
+
print(f"Wiki not found at {path}")
|
|
154
|
+
return
|
|
155
|
+
from ..services.wiki_backend import wiki_list_pages
|
|
156
|
+
pages = wiki_list_pages(path)
|
|
157
|
+
if not pages:
|
|
158
|
+
print(f"No pages found in wiki {path}")
|
|
159
|
+
return
|
|
160
|
+
print(f"Wiki ({path}):")
|
|
161
|
+
print("")
|
|
162
|
+
current_type = None
|
|
163
|
+
for page in pages:
|
|
164
|
+
if page["type"] != current_type:
|
|
165
|
+
current_type = page["type"]
|
|
166
|
+
print(f" {Color.CYAN}{current_type}{Color.NC}")
|
|
167
|
+
tags_str = f" [{', '.join(page['tags'])}]" if page["tags"] else ""
|
|
168
|
+
print(f" {page['file']}{tags_str}")
|
|
169
|
+
return
|
|
170
|
+
|
|
113
171
|
if backend == "obsidian":
|
|
114
172
|
if path is None or not path.exists():
|
|
115
173
|
print(f"Obsidian vault not found at {path}")
|
|
@@ -361,6 +419,96 @@ def format_size(size_bytes: int) -> str:
|
|
|
361
419
|
return f"{original_size:.1f}P"
|
|
362
420
|
|
|
363
421
|
|
|
422
|
+
def do_ingest(title: str, body: str, concepts: Optional[list] = None, entities: Optional[list] = None, tags: Optional[list] = None) -> None:
|
|
423
|
+
"""Ingest a source into the wiki backend."""
|
|
424
|
+
backend, path = _load_memory_config()
|
|
425
|
+
if backend != "wiki":
|
|
426
|
+
print("The `ingest` subcommand is only available for the wiki backend.")
|
|
427
|
+
return
|
|
428
|
+
if path is None:
|
|
429
|
+
print("Memory path not configured.")
|
|
430
|
+
return
|
|
431
|
+
from ..services.wiki_backend import wiki_ingest
|
|
432
|
+
result = wiki_ingest(
|
|
433
|
+
path,
|
|
434
|
+
title=title,
|
|
435
|
+
body=body,
|
|
436
|
+
concepts=concepts or [],
|
|
437
|
+
entities=entities or [],
|
|
438
|
+
tags=tags or [],
|
|
439
|
+
)
|
|
440
|
+
source_paths = result.get("source", [])
|
|
441
|
+
concept_paths = result.get("concepts", [])
|
|
442
|
+
entity_paths = result.get("entities", [])
|
|
443
|
+
print(f"{Color.GREEN}Ingested: {title}{Color.NC}")
|
|
444
|
+
for p in source_paths:
|
|
445
|
+
print(f" source: {p}")
|
|
446
|
+
for p in concept_paths:
|
|
447
|
+
print(f" concept: {p}")
|
|
448
|
+
for p in entity_paths:
|
|
449
|
+
print(f" entity: {p}")
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def do_query(keyword: str) -> None:
|
|
453
|
+
"""Search wiki pages by keyword."""
|
|
454
|
+
backend, path = _load_memory_config()
|
|
455
|
+
if backend != "wiki":
|
|
456
|
+
print("The `query` subcommand is only available for the wiki backend.")
|
|
457
|
+
return
|
|
458
|
+
if path is None:
|
|
459
|
+
print("Memory path not configured.")
|
|
460
|
+
return
|
|
461
|
+
from ..services.wiki_backend import wiki_query
|
|
462
|
+
results = wiki_query(path, keyword)
|
|
463
|
+
if not results:
|
|
464
|
+
print(f"No results found for: {keyword}")
|
|
465
|
+
return
|
|
466
|
+
print(f"Results for '{keyword}' ({len(results)} found):")
|
|
467
|
+
print("")
|
|
468
|
+
for r in results:
|
|
469
|
+
print(f" {Color.CYAN}[{r['type']}]{Color.NC} {r['title']}")
|
|
470
|
+
print(f" {r['path']}")
|
|
471
|
+
if r["snippet"]:
|
|
472
|
+
print(f" ...{r['snippet']}...")
|
|
473
|
+
print("")
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def do_lint() -> None:
|
|
477
|
+
"""Check wiki health."""
|
|
478
|
+
backend, path = _load_memory_config()
|
|
479
|
+
if backend != "wiki":
|
|
480
|
+
print("The `lint` subcommand is only available for the wiki backend.")
|
|
481
|
+
return
|
|
482
|
+
if path is None:
|
|
483
|
+
print("Memory path not configured.")
|
|
484
|
+
return
|
|
485
|
+
from ..services.wiki_backend import wiki_lint
|
|
486
|
+
issues = wiki_lint(path)
|
|
487
|
+
orphans = issues.get("orphans", [])
|
|
488
|
+
broken = issues.get("broken_links", [])
|
|
489
|
+
stale = issues.get("stale_index", [])
|
|
490
|
+
|
|
491
|
+
if not orphans and not broken and not stale:
|
|
492
|
+
print(f"{Color.GREEN}Wiki is healthy — no issues found.{Color.NC}")
|
|
493
|
+
return
|
|
494
|
+
|
|
495
|
+
if orphans:
|
|
496
|
+
print(f"{Color.YELLOW}Orphans ({len(orphans)} pages not linked from anywhere):{Color.NC}")
|
|
497
|
+
for p in orphans:
|
|
498
|
+
print(f" {p}")
|
|
499
|
+
print("")
|
|
500
|
+
if broken:
|
|
501
|
+
print(f"{Color.YELLOW}Broken links ({len(broken)}):{Color.NC}")
|
|
502
|
+
for b in broken:
|
|
503
|
+
print(f" {b}")
|
|
504
|
+
print("")
|
|
505
|
+
if stale:
|
|
506
|
+
print(f"{Color.YELLOW}Stale index ({len(stale)} pages newer than index.md):{Color.NC}")
|
|
507
|
+
for s in stale:
|
|
508
|
+
print(f" {s}")
|
|
509
|
+
print(f" Run: agent-notes memory index")
|
|
510
|
+
|
|
511
|
+
|
|
364
512
|
def do_migrate() -> None:
|
|
365
513
|
"""Migrate vault from per-project layout to flat shared layout with new filenames."""
|
|
366
514
|
import re
|
|
@@ -574,6 +722,25 @@ def memory(action: str = "list", name: Optional[str] = None, extra: Optional[lis
|
|
|
574
722
|
do_import()
|
|
575
723
|
elif action == "migrate":
|
|
576
724
|
do_migrate()
|
|
725
|
+
elif action == "ingest":
|
|
726
|
+
if not name:
|
|
727
|
+
print("Error: ingest requires a title.")
|
|
728
|
+
exit(1)
|
|
729
|
+
body = extra[0] if extra else ""
|
|
730
|
+
concepts_csv = extra[1] if extra and len(extra) > 1 else ""
|
|
731
|
+
entities_csv = extra[2] if extra and len(extra) > 2 else ""
|
|
732
|
+
tags_csv = extra[3] if extra and len(extra) > 3 else ""
|
|
733
|
+
concepts = [c.strip() for c in concepts_csv.split(",") if c.strip()] if concepts_csv else None
|
|
734
|
+
entities = [e.strip() for e in entities_csv.split(",") if e.strip()] if entities_csv else None
|
|
735
|
+
tags = [t.strip() for t in tags_csv.split(",") if t.strip()] if tags_csv else None
|
|
736
|
+
do_ingest(name, body, concepts=concepts, entities=entities, tags=tags)
|
|
737
|
+
elif action == "query":
|
|
738
|
+
if not name:
|
|
739
|
+
print("Error: query requires a keyword.")
|
|
740
|
+
exit(1)
|
|
741
|
+
do_query(name)
|
|
742
|
+
elif action == "lint":
|
|
743
|
+
do_lint()
|
|
577
744
|
else:
|
|
578
745
|
print(f"Unknown command: {action}")
|
|
579
746
|
show_help()
|
|
@@ -46,6 +46,8 @@ def memory_dir_for_backend(backend: str, custom_path: str = "") -> Optional[Path
|
|
|
46
46
|
return Path(custom_path).expanduser()
|
|
47
47
|
if backend == "obsidian":
|
|
48
48
|
return Path.home() / "Documents" / "Obsidian Vault" / "agent-notes"
|
|
49
|
+
if backend == "wiki":
|
|
50
|
+
return Path.home() / "Documents" / "Obsidian Vault" / "agent-wiki"
|
|
49
51
|
return MEMORY_DIR # local default: ~/.claude/agent-memory
|
|
50
52
|
|
|
51
53
|
def get_version() -> str:
|
|
@@ -7,7 +7,7 @@ from typing import Optional
|
|
|
7
7
|
|
|
8
8
|
@dataclass
|
|
9
9
|
class MemoryConfig:
|
|
10
|
-
backend: str = "local" # "obsidian" | "local" | "none"
|
|
10
|
+
backend: str = "local" # "obsidian" | "local" | "wiki" | "none"
|
|
11
11
|
path: str = "" # vault root (obsidian) or memory dir (local). empty = use default
|
|
12
12
|
|
|
13
13
|
|
|
@@ -53,6 +53,12 @@ def _current_session_id() -> Optional[str]:
|
|
|
53
53
|
return None
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
def _current_project_name() -> str:
|
|
57
|
+
"""Return the current working directory's name as the project name."""
|
|
58
|
+
name = Path.cwd().name
|
|
59
|
+
return name or ""
|
|
60
|
+
|
|
61
|
+
|
|
56
62
|
# ── Obsidian backend ───────────────────────────────────────────────────────────
|
|
57
63
|
|
|
58
64
|
def obsidian_init(vault: Path) -> None:
|
|
@@ -107,9 +113,12 @@ def _build_note(
|
|
|
107
113
|
agent: str,
|
|
108
114
|
session_stem: Optional[str],
|
|
109
115
|
created_at: str,
|
|
116
|
+
project: str = "",
|
|
110
117
|
) -> str:
|
|
111
118
|
"""Render the canonical note content (frontmatter + heading + body + Related section)."""
|
|
112
119
|
lines = ["---", f"created_at: {created_at}", f"type: {note_type}"]
|
|
120
|
+
if project:
|
|
121
|
+
lines.append(f"project: {project}")
|
|
113
122
|
if session_stem and note_type != "session":
|
|
114
123
|
lines.append(f"session: {session_stem}")
|
|
115
124
|
if agent:
|
|
@@ -178,6 +187,9 @@ def obsidian_write_note(
|
|
|
178
187
|
else:
|
|
179
188
|
session_id = None
|
|
180
189
|
|
|
190
|
+
if not project:
|
|
191
|
+
project = _current_project_name()
|
|
192
|
+
|
|
181
193
|
today = _today()
|
|
182
194
|
|
|
183
195
|
if note_type == "session" and session_id:
|
|
@@ -185,7 +197,7 @@ def obsidian_write_note(
|
|
|
185
197
|
# But first check if an existing file already has this session_id (any date prefix)
|
|
186
198
|
existing = _find_session_note(vault, session_id)
|
|
187
199
|
if existing is not None:
|
|
188
|
-
# Append to existing session note
|
|
200
|
+
# Append to existing session note — preserve existing frontmatter (including project)
|
|
189
201
|
text = existing.read_text()
|
|
190
202
|
fm, existing_body = _parse_frontmatter(text)
|
|
191
203
|
if "created_at" not in fm:
|
|
@@ -193,6 +205,9 @@ def obsidian_write_note(
|
|
|
193
205
|
if re.fullmatch(r"\d{4}-\d{2}-\d{2}", created_at):
|
|
194
206
|
created_at = f"{created_at}T00:00:00Z"
|
|
195
207
|
new_fm_lines = ["---", f"created_at: {created_at}", f"type: {note_type}"]
|
|
208
|
+
existing_project = fm.get("project", "")
|
|
209
|
+
if existing_project:
|
|
210
|
+
new_fm_lines.append(f"project: {existing_project}")
|
|
196
211
|
if agent:
|
|
197
212
|
new_fm_lines.append(f"agent: {agent}")
|
|
198
213
|
new_fm_lines.append("---")
|
|
@@ -206,7 +221,7 @@ def obsidian_write_note(
|
|
|
206
221
|
path = folder / filename
|
|
207
222
|
path.write_text(_build_note(
|
|
208
223
|
title=title, body=body, note_type=note_type,
|
|
209
|
-
agent=agent, session_stem=None, created_at=created_at,
|
|
224
|
+
agent=agent, session_stem=None, created_at=created_at, project=project,
|
|
210
225
|
))
|
|
211
226
|
elif note_type == "session":
|
|
212
227
|
# No session_id available — fall back to timestamp+slug
|
|
@@ -215,7 +230,7 @@ def obsidian_write_note(
|
|
|
215
230
|
path = folder / filename
|
|
216
231
|
path.write_text(_build_note(
|
|
217
232
|
title=title, body=body, note_type=note_type,
|
|
218
|
-
agent=agent, session_stem=None, created_at=created_at,
|
|
233
|
+
agent=agent, session_stem=None, created_at=created_at, project=project,
|
|
219
234
|
))
|
|
220
235
|
else:
|
|
221
236
|
# Non-session note
|
|
@@ -232,7 +247,7 @@ def obsidian_write_note(
|
|
|
232
247
|
path = folder / filename
|
|
233
248
|
path.write_text(_build_note(
|
|
234
249
|
title=title, body=body, note_type=note_type,
|
|
235
|
-
agent=agent, session_stem=session_stem, created_at=created_at,
|
|
250
|
+
agent=agent, session_stem=session_stem, created_at=created_at, project=project,
|
|
236
251
|
))
|
|
237
252
|
|
|
238
253
|
# Auto-link to session note
|
|
@@ -265,7 +280,8 @@ def _parse_note_metadata(path: Path) -> dict:
|
|
|
265
280
|
(l.lstrip("# ").strip() for l in full_text.splitlines() if l.startswith("# ")),
|
|
266
281
|
path.stem,
|
|
267
282
|
)
|
|
268
|
-
|
|
283
|
+
project = fm.get("project", "")
|
|
284
|
+
return {"created_at": created_at, "type": note_type, "title": title, "project": project}
|
|
269
285
|
|
|
270
286
|
|
|
271
287
|
def obsidian_regenerate_index(vault: Path) -> None:
|
|
@@ -299,7 +315,8 @@ def obsidian_regenerate_index(vault: Path) -> None:
|
|
|
299
315
|
display_dt = f"{dt_str[:10]} {dt_str[11:16]}"
|
|
300
316
|
else:
|
|
301
317
|
display_dt = dt_str[:16] if len(dt_str) >= 16 else dt_str
|
|
302
|
-
|
|
318
|
+
project = meta.get("project", "") or _current_project_name()
|
|
319
|
+
lines.append(f"- [[{stem}|{display_dt}]] - {project}({meta['type']})")
|
|
303
320
|
|
|
304
321
|
(vault / "Index.md").write_text("\n".join(lines) + "\n")
|
|
305
322
|
|