Skip to content

feat(status): surface selected backend per DB engine entry#12

Merged
ikeikeikeike merged 1 commit into
mainfrom
feat/L5d-status-backend
Jun 17, 2026
Merged

feat(status): surface selected backend per DB engine entry#12
ikeikeikeike merged 1 commit into
mainfrom
feat/L5d-status-backend

Conversation

@ikeikeikeike

Copy link
Copy Markdown
Member

Summary

`bough status` now reports the lifecycle backend each DB engine
kind would run against, so an operator can spot-check the auto-detect
outcome without re-running `bough create`.

For each entry whose Kind matches a YAML database:

  • explicit `databases[].backend:` value → shown as-is
  • empty YAML value → `backend.Detect()` result annotated `(auto)`
  • detect failure / timeout (3 s cap) → `unresolved`

Non-DB port kinds (api / gateway / ...) keep their existing output
shape; the JSON `backend` field is `omitempty`.

Example

$ bough status
F-X/mysql :: port=43621, listening=true, pid=12345, backend=docker (auto)
F-X/api   :: port=45621, listening=false, pid=0

Test plan

  • `go build ./...` succeeds in `nix develop .#ci`
  • `go test ./internal/cli/...` passes
  • `golangci-lint run ./...` 0 issues

`bough status` now reports the lifecycle runtime each DB engine kind
(mysql / postgres / redis / elasticsearch) would run against, so an
operator can spot-check the auto-detect outcome without re-running
`bough create`.

  $ bough status
  F-X/mysql         :: port=43621, listening=true, pid=12345, backend=docker (auto)
  F-X/redis         :: port=54621, listening=true, pid=12346, backend=docker
  F-X/elasticsearch :: port=57621, listening=true, pid=12347, backend=nix (auto)
  F-X/api           :: port=45621, listening=false, pid=0
  F-X/gateway       :: port=48421, listening=false, pid=0

For each entry whose Kind matches a YAML-declared database:

- If `databases[].backend:` is set explicitly in the YAML, use it.
- Else fall back to `backend.Detect()` (the same probe `bough create`
  runs) and annotate the result `<backend> (auto)` so the operator
  sees both pieces of context.
- Detect() is invoked at most once per `bough status` call, with a
  3-second cap so an unresponsive nix daemon does not stall the
  output. On timeout the affected entries get `backend=unresolved`.

Non-DB port kinds (api / gateway / ...) keep their existing output
shape; the JSON `backend` field is omitempty so consumers that
ignored it before keep working.

Follow-up to the Λ-5b agent's optional v0.3 recommendation.
@ikeikeikeike
ikeikeikeike merged commit 13e3b50 into main Jun 17, 2026
1 check passed
@ikeikeikeike
ikeikeikeike deleted the feat/L5d-status-backend branch June 17, 2026 01:51
ikeikeikeike added a commit that referenced this pull request Jun 21, 2026
… propagation / cache gen / cache namespace / Export pagination

#10 instinctToMetadata + writeInstinct skip zero-value time.Time
so a freshly constructed Instinct does not serialise a
-6795364578871 epoch into mem0 metadata or the JSONL export
(which would round-trip back as a garbage "year 0001" timestamp).

#11 The YAML / JSONL Export now carries dedupe_key +
source_event_id alongside each row, and Import's parser returns
an importRow struct that preserves both tokens. The host's
Store-by-dedupe contract therefore survives sqlite Export → mem0
Import round trips end-to-end.

#12 queryCache gains a monotonic invalidation generation. Query
captures gen before the HTTP roundtrip and hands it to put; put
silently drops the write when invalidateScope has bumped gen in
the interim. A concurrent Store / Forget / Import can no longer
race a slow Query and pin a stale response in cache for cacheTTL.

#13 cacheKey gains a namespace field, populated via the new
Provider.cacheKeyFor method, so two tenants sharing one Provider
with different namespaces never share cache entries even when
Scope shape matches.

#15 Export now paginates: it loops GET /api/v1/memories/?page=N
until a less-than-page-size batch comes back. Long scopes (>100
instincts) no longer silently truncate at the first page.

Build clean, plugins/memory/mem0 unit tests pass.
ikeikeikeike added a commit that referenced this pull request Jun 21, 2026
… propagation / cache gen / cache namespace / Export pagination

#10 instinctToMetadata + writeInstinct skip zero-value time.Time
so a freshly constructed Instinct does not serialise a
-6795364578871 epoch into mem0 metadata or the JSONL export
(which would round-trip back as a garbage "year 0001" timestamp).

#11 The YAML / JSONL Export now carries dedupe_key +
source_event_id alongside each row, and Import's parser returns
an importRow struct that preserves both tokens. The host's
Store-by-dedupe contract therefore survives sqlite Export → mem0
Import round trips end-to-end.

#12 queryCache gains a monotonic invalidation generation. Query
captures gen before the HTTP roundtrip and hands it to put; put
silently drops the write when invalidateScope has bumped gen in
the interim. A concurrent Store / Forget / Import can no longer
race a slow Query and pin a stale response in cache for cacheTTL.

#13 cacheKey gains a namespace field, populated via the new
Provider.cacheKeyFor method, so two tenants sharing one Provider
with different namespaces never share cache entries even when
Scope shape matches.

#15 Export now paginates: it loops GET /api/v1/memories/?page=N
until a less-than-page-size batch comes back. Long scopes (>100
instincts) no longer silently truncate at the first page.

Build clean, plugins/memory/mem0 unit tests pass.
ikeikeikeike added a commit that referenced this pull request Jul 4, 2026
fix: retrospective review fixes for merged PRs #9/#10/#11/#12/#18/#19/#20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant