# Contributing to claude-obsidian Thanks for your interest in improving this plugin. claude-obsidian is a small, focused project; contributions that match its philosophy land quickly. ## Philosophy Three constraints shape every change: 1. **Read before write.** Every contribution starts by reading the affected files, their tests, and their callers. Removals break assumptions as often as additions. 2. **Smallest unit that works.** No speculative abstraction. Complexity is earned, not anticipated. Three real callers minimum before an abstraction lands. 3. **Failure is the spec.** Every new failure mode needs explicit handling. Untrusted input, network calls, and state changes need an explicit blast-radius answer. The full kernel lives in [`/best-practices`](https://github.com/AgriciDaniel/best-practices) (composable Claude Code skill). The pre-commit verifier agent at [`agents/verifier.md`](agents/verifier.md) enforces it for non-trivial changes. ## Workflow ### 1. Open an issue first (for non-trivial changes) For typo fixes, doc clarifications, or single-line changes, skip straight to a PR. For anything bigger: - Open an issue using the bug-report or feature-request template - Describe the problem, the proposed change, and the blast radius - Wait for a thumbs-up before investing time ### 2. Fork + branch Contributions are accepted on the public canonical repo. Fork [`AgriciDaniel/claude-obsidian`](https://github.com/AgriciDaniel/claude-obsidian) on GitHub, then: ```bash git clone https://github.com//claude-obsidian.git cd claude-obsidian git checkout -b your-feature-name ``` > â„šī¸ The public repo (`AgriciDaniel/claude-obsidian`) is the canonical source of truth. Raise all PRs against it. AI Marketing Hub Pro members working from the early-access mirror (`AI-Marketing-Hub/claude-obsidian`) should target the public canonical too, so contributions land in one place. Branch names: `fix/...`, `feat/...`, `docs/...`, `refactor/...`. ### 3. Set up locally The plugin runs anywhere Claude Code runs. For development: ```bash # Run the hermetic test suite — required before submitting a PR make test # Optionally provision the v1.7 retrieval pipeline (requires consent for API egress) bash bin/setup-retrieve.sh # Optionally pick a methodology mode for testing the v1.8 routing bash bin/setup-mode.sh ``` ### 4. Make the change Follow the six-cut kernel: - Read every file you're touching - Name new identifiers like the next reader is hostile - Smallest unit that works - Delete more than you add (when superseding) - Evidence over intuition (tests for new behavior) - Failure-mode + undo plan documented If you add a new skill, agent, script, or hook, also add a test under `tests/`. The 9 hermetic test suites are the project's safety net. ### 5. Run the tests ```bash make test ``` All 9 suites must pass (~1240 assertions). Tests are hermetic: no network, no ollama, no Anthropic API. If your change adds a network call, gate it behind a `--consent`/`--allow-egress`/env-var pattern matching `scripts/contextual-prefix.py` or `scripts/tiling-check.py`. ### 6. Run the verifier (optional but recommended) For multi-file changes: ```bash # After git add, before git commit, dispatch the verifier agent # (Claude Code: invoke agents/verifier.md on the staged diff) ``` The verifier applies the six-cut + agent kernel to your staged diff and returns findings in BLOCKER / HIGH / MEDIUM / LOW tiers. Address BLOCKER + HIGH before committing. ### 7. Commit Commit message convention (Conventional Commits): ``` (): ``` Types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `perf`, `style`. Example: ``` fix(wiki-mode): close path-traversal in route_path safe_name Sanitize routing input via safe_name() before string-concat into the vault-relative path. Adds 9 hermetic test assertions for traversal vectors. Closes audit finding S1. ``` ### 8. Update CHANGELOG.md Add an entry under `## [Unreleased]` (create the section if needed). Follow the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format: ```markdown ## [Unreleased] ### Added - Description of new feature ### Fixed - Description of bug fix ``` The maintainer will move your entry to a versioned section at release time. ### 9. Open a PR Use the PR template. Required fields: - What changed - Why - How it was tested (paste `make test` output if relevant) - Audit/verifier results if applicable PRs are reviewed against the kernel. Expect feedback on naming, scope, and failure-mode coverage. ## Testing standards - **Hermetic.** No network, no external services, no user-specific environment. - **Fast.** The full suite runs in under a minute. - **Deterministic.** Same input → same output, every time. - **Documented.** Every test asserts a named behavior, not a coincidence. If you can't make your test hermetic, ask in the issue whether a mocked alternative is acceptable. ## What we will NOT merge - Code without tests for new behavior - Speculative abstractions (no real callers yet) - Network calls without an explicit consent gate - Path construction from user input without sanitization (see `scripts/wiki-mode.py:safe_name`) - Skills/agents that shell out without documenting the failure mode - Anything that breaks the existing test suite without a documented reason ## Security Found a vulnerability? Do NOT open a public issue. See [SECURITY.md](SECURITY.md) for disclosure. ## License By contributing, you agree your contributions are licensed under the [MIT License](LICENSE). ## Code of Conduct Participation is governed by the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).