Commit Graph

1428 Commits

Author SHA1 Message Date
phernandez 2c30922e65 docs(core): add Basic Machines agent style guidance
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 15:37:43 -05:00
phernandez e8cda55ddb test(cli): make copyto path assertions Windows-portable
The Windows SQLite unit job failed because two new copyto tests asserted on
raw POSIX dest strings. On Windows `str(Path("/tmp/research"))` renders with
backslashes, so the copyto dest is `\tmp\research/notes/...` (rclone accepts the
mixed separators — the product is fine). Compare the local dest via `Path(...)`
like the other tests, which normalizes separators cross-platform.

Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 13:00:48 -05:00
phernandez c850450ddf fix(cli): address push/pull review feedback (fatal-error guard, UX, tests)
From the Codex and claude-review automated reviews on PR #917:

- project_diff: fail fast on fatal `rclone check` errors. A non-zero exit with
  no combined listing (auth/network/missing-remote) previously produced an empty
  plan, so the transfer ran as a no-op and reported success. Now raises
  RcloneError with rclone's stderr. (Codex P2 / claude-review #2)
- sync-setup "Next steps": stop pointing every user at the now-Personal-only
  `bm cloud sync`; lead with the Team-safe `pull`/`push` and note bisync is
  Personal-only. (claude-review #1)
- Cosmetic: capitalize the push/pull abort headlines for consistency; document
  the two ConflictStrategy definitions (Typer enum vs engine Literal). (nits)
- Tests: cover keep-local+pull and keep-cloud+push (preserve-destination cases),
  project_transfer aborting on a mid-loop conflict-copy failure, and project_diff
  raising on a fatal check error vs not raising on a normal differences exit.

Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 12:30:20 -05:00
phernandez ad1f8621f1 docs(cli): document cloud push/pull and Personal-only sync/bisync
Update docs/cloud-cli.md for the docs site:
- Add a Team Workspaces push/pull section (additive, git-style transfers,
  the --on-conflict {fail|keep-local|keep-cloud|keep-both} resolution, and the
  no-baseline limitations tracked by #862).
- Mark `sync` and `bisync` as Personal-workspace-only mirrors and point Team
  users at push/pull, with a Personal-vs-Team overview table.
- Fix stale command namespace: `bm project sync|bisync|check|bisync-reset` ->
  `bm cloud ...` (these live under `bm cloud`, not `bm project`).
- Add push/pull to the command reference and the summary workflows.

Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 12:25:22 -05:00
phernandez a7937d4066 fix(cli): compare by checksum on overwrite push/pull to match conflict detection
Second code-review finding (PLAUSIBLE): project_diff detects conflicts with
`rclone check` (content/hash), but project_copy used `rclone copy` with its
default size+modtime comparison. On an overwrite strategy (keep-cloud on pull /
keep-local on push), copy could skip a file the diff had flagged as a conflict
when sizes matched and the destination was not older — silently ignoring the
user's explicit choice.

Add `--checksum` to the overwrite copy so the transfer decision uses the same
content basis as detection. New-only mode is unaffected: `--ignore-existing`
skips by existence, so the comparison basis is irrelevant there. project_sync
(the Personal-only mirror) is untouched and keeps its default comparison.

Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 11:48:20 -05:00
phernandez 9dbe313193 fix(cli): add --local-no-preallocate to conflict-copy copyto
Code-review finding: project_copy_file built its `rclone copyto` command
inline and omitted `--local-no-preallocate`. On a `pull --on-conflict keep-both`
that copyto writes the conflict copy to the local filesystem, which is exactly
the case the flag guards (NUL byte padding on virtual filesystems such as
Google Drive File Stream). Every other transfer path adds it via
_build_transfer_cmd; bring copyto in line.

Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 11:44:20 -05:00
phernandez e23363606a feat(cli): add Team-safe cloud push/pull and gate sync to Personal workspaces
Adds `bm cloud push` and `bm cloud pull` as git-style, fail-safe transfer
primitives that are usable on Team workspaces (issue #858), and restricts the
destructive `bm cloud sync` mirror to Personal workspaces.

Why
- `bm cloud sync` is a destructive local->cloud mirror; on a shared Team bucket
  it can delete a teammate's files. The only pull path was two-way `bisync`,
  which is already Personal-only (#849).
- Teams need a safe way to fetch teammates' notes and add their own without one
  stale local tree becoming authoritative for shared cloud state.

What
- push = `rclone copy` local->cloud, pull = `rclone copy` cloud->local. Both are
  additive (never delete on the destination), so neither can damage shared state.
- Conflicts (a file that differs on both sides) abort by default and list the
  paths, like git refusing to clobber local changes / rejecting a stale push.
  `--on-conflict {fail|keep-local|keep-cloud|keep-both}` lets the user decide;
  no vague --force, no silent winner.
- `sync` now requires a Personal workspace; its guard and the bisync guard point
  Team users at push/pull.

Limitations (surfaced in --help and command output, tracked by #862):
- No sync baseline yet, so deletions are not propagated and every divergence is
  treated as a conflict rather than auto-resolved. Real three-way merge needs
  the per-client manifest + Tigris snapshot baseline designed in #862.

Implementation
- rclone_commands.py: shared `_build_transfer_cmd`/`_transfer_endpoints`;
  refactor `project_sync` onto them (no behavior change); add `project_diff`
  (conflict detection via `rclone check --combined`), `project_copy`,
  `project_copy_file`, and `project_transfer` (strategy dispatch).
- project_sync.py: new `push`/`pull` commands (ungated, Team-safe) with
  `--on-conflict`/`--dry-run`; gate `sync` to Personal via a per-command guard
  message.
- Tests at the rclone-argv and CLI-command levels; existing sync/bisync tests
  updated for the new gating and messages.

Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 11:35:13 -05:00
Paul Hernandez a8d034b940 fix(mcp): point move mismatch guidance at landing path (#916)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-08 10:42:38 -05:00
Paul Hernandez 7c0937f658 fix(mcp): validate navigation pagination and fix recent_activity project display (#915)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 23:03:00 -05:00
Paul Hernandez 8570d96bad fix(cli): align bm tool commands with MCP (error exits, overwrite, category, default) (#913)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:56:43 -05:00
Paul Hernandez 480a2d9468 fix(mcp): resolve memory:// in move_note and stop false cross-project rejections (#914)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:44:08 -05:00
Paul Hernandez df7452e3ba fix(core): make note_types search filter case-insensitive (#912)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:44:04 -05:00
Paul Hernandez 85a8e59d0f fix(core): split comma-separated tags in parse_tags (#911)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:44:01 -05:00
Paul Hernandez 07cb7a606b docs(core): mark LiteLLM provider experimental (#899)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 20:13:54 -05:00
Paul Hernandez 0ef03edde6 feat(cli): add --type to the write-note tool command (#907)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 20:06:44 -05:00
Paul Hernandez efe43a10ea feat(cli): add --wait and --timeout to bm status (#906)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 19:58:02 -05:00
Paul Hernandez 4fe6fe09c8 feat(core): add observation category filter to search (#908)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 19:57:19 -05:00
Paul Hernandez 8acdb49a41 fix(core): reuse a single embedding provider per process (#903)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 19:14:07 -05:00
Paul Hernandez f7304bf553 feat(cli): improve workspace and cloud bisync command discoverability (#905)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 18:18:17 -05:00
Paul Hernandez 5b034f081d fix(core): self-heal corrupt FastEmbed model cache (#900)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 17:37:30 -05:00
Paul Hernandez 271c883ea8 fix(core): load sqlite-vec for embedding-status query (#901)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 17:37:27 -05:00
Paul Hernandez 816ee85fb9 fix(core): prevent asyncpg engine-dispose crash on Postgres backend (#902)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 17:37:23 -05:00
Paul Hernandez 3ba3a9504d fix(mcp): stop move_note reporting false success across boundaries (#904)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 17:37:20 -05:00
Paul Hernandez 1667cdc000 test(ci): normalize setup overwrite assertion (#898)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-06 23:20:06 -05:00
Sourish Chakraborty f916662ff3 fix(core): allow cross-project context traversal 2026-06-06 21:43:21 -05:00
DoubleDeeRuffy 0c9800cd3b fix(sync): use strict deferred relation resolution 2026-06-06 21:43:09 -05:00
Adit Karode 476239d878 feat(cli): add delete-note tool command 2026-06-06 21:41:46 -05:00
DoubleDeeRuffy 20bb19f4cd fix(mcp): resolve write-note overwrite conflicts 2026-06-06 21:41:36 -05:00
tk f6565b9d23 fix(core): L2-normalize FastEmbed vectors (#843)
L2-normalizes FastEmbed output vectors at the provider boundary so SQLite vector scoring keeps its unit-vector contract for custom FastEmbed models such as multilingual MiniLM variants.

Zero vectors are preserved as-is to avoid division errors, and the provider tests cover both non-unit vectors and zero-vector behavior.

Verification:
- uv run pytest tests/repository/test_fastembed_provider.py -q
- uv run ruff check src/basic_memory/repository/fastembed_provider.py tests/repository/test_fastembed_provider.py
- uv run ruff format --check src/basic_memory/repository/fastembed_provider.py tests/repository/test_fastembed_provider.py

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: tk-pkm111 <133480534+tk-pkm111@users.noreply.github.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-06 17:15:19 -05:00
Aarish Alam b6e8c636ce feat(core): add LiteLLM embedding provider (#809)
Adds LiteLLM as a semantic embedding provider, including provider configuration, vector normalization, live-provider evaluation tooling, and documentation for OpenAI, Cohere, Azure Foundry, Azure OpenAI, and NVIDIA NIM-style cases.

Maintainer follow-up on this PR added provider hardening, asymmetric document/query embedding support, dimension-forwarding controls, SQLite/Postgres vector invalidation coverage, and the repeatable live LiteLLM harness.

Verification:
- Full base-repo Tests workflow passed for 3d4e092ceb: https://github.com/basicmachines-co/basic-memory/actions/runs/27072071785
- Live LiteLLM harness passed locally for OpenAI, Cohere, and Azure Foundry.

Co-authored-by: Aarish Alam <arishalam121@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: RheagalFire <arishalam121@gmail.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-06 17:13:09 -05:00
Paul Hernandez 442fd1523c fix(plugins): include codex in shared version bump (#897)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-05 18:34:57 -05:00
Paul Hernandez ce4b5d47a0 fix(skills): reject invalid frontmatter YAML (#896)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-05 13:14:27 -05:00
phernandez 59e865c079 chore: update version to 0.21.6 for v0.21.6 release
Signed-off-by: phernandez <paul@basicmachines.co>
v0.21.6
2026-06-04 23:41:42 -05:00
phernandez 96b6b21a88 docs: add v0.21.6 changelog entry
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-04 23:41:30 -05:00
Paul Hernandez 5973f9b787 feat(plugins): add codex plugin package (#894)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-04 23:14:07 -05:00
Paul Hernandez 8887267256 fix(ci): improve auto bm note narrative (#893)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-04 22:34:57 -05:00
Paul Hernandez a6cfed96f1 fix(ci): allow ci PR title scope
Allows ci as a semantic PR title scope and covers the workflow config with a regression test.
2026-06-04 21:05:29 -05:00
Paul Hernandez 2de8183e85 fix(ci): require all codex synthesis schema fields
Fixes the Auto BM Codex structured-output schema guardrail so live synthesis can run.
2026-06-04 20:48:55 -05:00
Paul Hernandez 0adbc12f09 docs(ci): document auto bm dogfood install
Documents the temporary checkout install used while dogfooding Auto BM before the next package release.
2026-06-04 20:44:51 -05:00
phernandez 80ca5a07fd ci(cli): dogfood auto bm workflow install
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-04 20:33:49 -05:00
phernandez 4502bd3c3b ci(cli): configure auto bm workflow
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-04 20:27:42 -05:00
phernandez b386502020 fix(cli): show copyable workspace identifiers
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-04 20:20:56 -05:00
phernandez 16ba55d7b4 feat(cli): add auto bm github ci
Signed-off-by: phernandez <paul@basicmachines.co>
2026-06-04 20:14:59 -05:00
Paul Hernandez 5458c35b35 refactor(plugins): prefix Claude Code plugin skills with bm- (#878)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:04:05 -05:00
Paul Hernandez fc2ee07076 feat(api): expose owning project on entity resolve
Expose project_external_id on v2 entity resolve responses so cloud callers can authorize cross-project targets without a second tenant DB lookup.
2026-06-02 18:01:17 -05:00
phernandez 61891f2e33 fix(plugins): address PR review — scope captureFolder to checkpoints, ASCII echo
Review feedback on #876:
- Codex (P2): the SessionStart "Where to write" brief said all auto-capture goes to
  captureFolder, but captureFolder is only the PreCompact checkpoint folder. Narrowed
  it — checkpoints go to captureFolder; decisions/tasks/notes follow
  placementConventions (or topic folders when none are set), so proactive captures
  aren't dumped into sessions/ alongside checkpoints.
- Claude review: replaced the em dash in the skills-source-guard echo string with a
  hyphen so the instruction's console output stays ASCII (CLAUDE.md compatibility).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-05-31 15:05:01 -05:00
phernandez 5f59ca49a2 docs(plugins): fold in setup debrief fixes — cloud-create, skills-source guard, shared-read cap
- Project mapping: document local vs cloud project creation — a cloud-workspace
  project needs a cloud-connected MCP server and a workspace selector; a purely
  local server fails to mkdir the cloud-style path. Pin cloud primaryProject to the
  external_id UUID.
- Install shared skills: guard against clobbering a source checkout — if ./skills is
  git-tracked and holds memory-* dirs (the skills' own source repo), skip the npx
  install instead of overwriting the working copy with published versions.
- Cloud/teams: warn that the SessionStart brief reads only the first 6 shared
  projects per session, so order the most relevant first when more are configured.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-05-31 15:05:01 -05:00
phernandez 2ba1ca8722 feat(plugins): make setup focus load-bearing, seed schemas via metadata, add smoke test
- Focus question is now load-bearing: it drives an adaptive light folder-structure
  suggestion and is stored. The placement step branches learn (existing project
  with notes) vs suggest (new/empty project) instead of only learning.
- Seed schema notes via the write_note `metadata` param instead of content
  frontmatter. The cloud write path silently coerces nested YAML to the string
  '[object Object]', corrupting schema/settings (basic-memory-cloud#1000); the
  metadata param round-trips correctly on both local and cloud.
- Surface placementConventions + captureFolder in the SessionStart brief so the
  output style's "follow stored placement conventions" reflex has something to
  follow — previously written by setup but never shown to Claude (dead config).
- Add a post-settings smoke test (run the hook's recall query, confirm routing)
  and a restart prompt gated on outputStyle in the close.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-05-31 15:05:01 -05:00
phernandez 4b6de80faa fix(plugins): hooks fall back to uvx/uv when no CLI binary is on PATH
Codex flagged (review 4397232451) that the hooks locate the CLI via
`command -v basic-memory || command -v bm`, but our own README recommends
connecting the MCP server as `claude mcp add basic-memory -- uvx basic-memory mcp`
— an ephemeral uv run that leaves NO binary on PATH. In that (recommended) setup
both hooks exited before doing anything, so the bridge silently did nothing even
though the MCP server worked.

Both hooks now resolve the CLI invocation as: prefer a `basic-memory`/`bm` binary
(fast), else fall back to `uvx basic-memory`, else `uv tool run basic-memory`, else
silent no-op. The launcher may be multi-token, so the embedded Python splits it with
shlex and prepends it to each command list. The uv cache is already warm from
running the MCP server, so the fallback is cheap.

Verified: with no binary on PATH but uvx present, SessionStart now produces a brief
(previously a silent no-op). Updated the README requirement to note uvx-only works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-05-31 12:31:08 -05:00
phernandez 1eb4cd154f fix(plugins): route UUID project refs consistently across all skills
Codex flagged /basic-memory:remember passing a UUID primaryProject as `project`
(review 4397206729) — the same routing bug already fixed in the hooks and the
share skill. Rather than fix only the flagged spot, audited every project-ref
site and made them all consistent:

- remember: route primaryProject as project_id when it's a UUID (was the flag)
- status: same for the primaryProject-scoped search_notes queries
- setup: same for the schema-seed write to primaryProject

share/SKILL.md and both hooks (session-start, pre-compact) already handle it.
That's now every place the plugin routes to a project ref — a project ref may be
a workspace-qualified name (-> project) or an external_id UUID (-> project_id),
and all six sites detect and route accordingly. Plugin validates.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-05-31 12:31:08 -05:00