Guidance for AI coding agents (and humans) working in this repository. Read it fully before making changes.
SQLite (and optional SQLCipher-encrypted) AbstractDB backend plugin for hivemind-core, storing HiveMind client records (API keys, crypto keys, ACLs).
Part of the HiveMind ecosystem — a
protocol for connecting satellite devices to a hub running
OpenVoiceOS. The hub is
HiveMind-core; the plugin
contract (AbstractDB) and loader live in
hivemind-plugin-manager.
pip install -e .
# encrypted-database support (SQLCipher / AES-256):
pip install -e ".[cipher]" # needs libsqlcipher system lib (apt install libsqlcipher-dev)pytest tests/Single suite lives in tests/test_sqlitedb.py. The repo's own tests.yml runs it with -p no:ovoscope and exercises both the plain and the SQLCipher path. Cipher tests need libsqlcipher-dev installed.
Ruff, via the shared lint.yml workflow (ruff: true, no pre-commit config present). No typecheck configured.
hivemind_sqlite_database/__init__.py— the entire plugin:SQLiteDBdataclass extendingAbstractDB. Schema creation,PRAGMA user_versionmigration (v1→v2 folds legacyintent_blacklist/skill_blacklistcolumns intoClient.metadata), and CRUD (add_item,search_by_value,get_client_by_id,__iter__,__len__,commit).hivemind_sqlite_database/version.py— version constants (do not edit).tests/test_sqlitedb.py— full behavioural suite.
Entry-point group: hivemind.database → hivemind-sqlite-db-plugin = hivemind_sqlite_database:SQLiteDB. Discovered by hivemind-plugin-manager; selected in hivemind-core config under database.module.
- Branches:
dev(work) andmaster(stable). NEVERmain. - Never edit
version.py; gh-automations bumps semver from conventional-commit prefixes (feat:/fix:/feat!:). - New repos private by default.
- Commit identity: JarbasAi jarbasai@mailfence.com.
- Reference
OpenVoiceOS/gh-automationsreusable workflows at@dev. - No Neon /
neon-*references. - No meta-commentary (no history, no dates) in code, docs, commits, or PRs — describe current state only.
- CI is provided by OpenVoiceOS/gh-automations.
- Never push
devormaster. Work on a feature branch and open a draft PR intodev. A human merges. You do not merge your own PRs. - Never merge or modify
Release X → masterPRs. They are the maintainer's stable-release mechanism, generated by automation. - One commit per PR (squash before pushing). Conventional commits;
feat:only for a user-visible new capability.fix:,docs:,chore:,ci:otherwise. - Disclose AI authorship. Every PR/issue/comment an agent writes carries, at
the top:
> 🤖 Auto-generated by <model> via Claude Code — NOT human-reviewed. Verify before acting.PR bodies are plain human prose (3–6 short paragraphs), no tables or section-symbol spray. - Never edit someone else's issue, PR description, or comment. Add a comment instead; on your own PRs, edit the body rather than piling on comments.
- No scratch files, committed virtualenvs,
__pycache__,.pyc,.egg-info, or build artifacts in a PR.git show --statshows only intended files.
- Floor pins only (
>=X.Y.Za1), bumped when a feature or fix is actually needed. No upper caps unless a specific released version is genuinely broken.pyproject.tomlcurrently pinshivemind-plugin-manager>=0.5.0,<1.0.0— that upper cap is a deviation from the floor-pins-only rule; treat removing it (once confirmed safe against 1.x) as a standing cleanup, not something to add to. - No lockfiles, ever. Target the latest alphas (
--prerelease=allow). - Everything in
pyproject.toml(deps, metadata, version). Never install from git — depend on a published PyPI alpha. - Apache-2.0. Do not add GPL/AGPL dependencies.
- Adversarial by default. A regression test must fail before the fix and pass
after — prove it by reverting only the source (
git apply -R, nevergit stashacross worktrees) and watching the test flip. - Tests must be mutation-proof: gutting the feature must fail the test. A test that only asserts a mock was called, without asserting the real behaviour, is weak — note it.
- Never skip a test because an optional dependency is missing (cipher tests need
libsqlcipher-dev; install it, do not skip). - CI green is permission to review, not to merge. A non-trivial change gets an adversarial review before it lands.
- This is the AUTH hot path for hivemind-core admission:
get_client_by_id(used byrefresh()) and the rest of the CRUD surface must fail SAFE. Every query is wrapped intry/except (sqlite3.Error, TypeError, ValueError), logs, and returnsNone/False/0on error — never raises past the plugin boundary, never fabricates a permissive client record. Preserve this on any change; a bug here means a bad key silently gets treated as absent rather than admitted, which is the safe direction — never invert it. - ACL fields (
can_broadcast,can_escalate,can_propagate, and the blacklists folded intometadata) must round-trip exactly throughadd_item→_row_to_client. Any schema or serialization change needs a test that writes aClientwith non-default ACL values and reads it back. _VALID_COLUMNSallowlist gatessearch_by_valuekeys; SQL column name is interpolated only after passing that frozenset (issue #1 tracks an SQL-security review — do not relax this allowlist without closing that concern).- Legacy
intent_blacklist/skill_blacklist/message_blacklistcolumns remain in the table but are NULLed on write; canonical data lives in themetadataJSON column.message_blacklistis purged entirely (not part ofClient). Do not resurrect writes to the legacy columns. migrate()guards ongetattr(AbstractDB, "SCHEMA_VERSION", 1)so it tolerates older hivemind-plugin-manager that predates the constant — do not assume the attribute exists.- WAL journal mode is enabled for both plain and encrypted DBs;
check_same_thread=Falsewith athreading.Lockguarding writes. Any new write path must take that lock. - Encrypted and plaintext databases are not interchangeable and there is no migration between them; lost passphrase = unrecoverable data.
tests.ymlis a repo-local workflow separate from the shared build-tests; both run the same suite.