Skip to content

refactor(connectors): rename lore-connectors to rac-connectors [roadmap:rac-connectors]#1

Merged
tcballard merged 34 commits into
mainfrom
claude/repo-topology-convergence-2a1awb
Jun 29, 2026
Merged

refactor(connectors): rename lore-connectors to rac-connectors [roadmap:rac-connectors]#1
tcballard merged 34 commits into
mainfrom
claude/repo-topology-convergence-2a1awb

Conversation

@tcballard

@tcballard tcballard commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Seeds the rac-connectors repository per ADR-092 (one repo per concern, subdir per member) and the rac/roadmaps/repo-topology/rac-connectors.md roadmap.

What this does

  • Brings the former itsthelore/lore-connectors in with full history preserved (31 commits + this rename commit; git log --follow src/rac_connectors/supermemory/connector.py traces back through the move).
  • Applies the rac-* naming:
    • distribution lore-connectorsrac-connectors (to be registered on PyPI)
    • import package src/lore_connectorssrc/rac_connectors — one dist, one subdir per integration (cognee/ letta/ mem0/ neo4j/ supermemory/ zep/)
    • CLI entry point lore-connectrac-connect
  • Updates the repo's own README badges/links and rac/ corpus references to the new slug/package.

Deliberately unchanged

  • Export-contract field names (lore_id) — renaming would break the data contract.
  • The "Lore" product brand in prose, and the itsthelore org name.
  • Connector behaviour: still thin export-contract consumers over the public rac CLI; no engine internals (ADR-073, ADR-063, ADR-002).

Scope note

This move also repackages + renames (beyond pure topology), per your direction. I'm recording the structure + PyPI-rename decision as a short ADR in rac-core (separate PR on the same feature branch).

Merging

  • main is an empty-root trunk already contained as an ancestor, so this fast-forwards cleanly. Create a merge commit — do not squash (squash would collapse the 31 preserved commits).
  • The former repo's CI workflows sit dormant under .github/workflows/ until you wire up / re-enable them; the publish workflow now targets the rac-connectors dist.

Remaining maintainer org actions

  • Archive lore-connectors with a redirect note to rac-connectors.
  • Register/own the rac-connectors name on PyPI; optionally set main as the default branch.

Execution tracking: asdecided/core#228 (rac-connectors item).

tcballard added 30 commits June 20, 2026 22:33
Establishes the Lore/RAC companion that pushes the corpus export into
external memory, RAG, and graph backends (rac-core ADR-073). Apache-2.0 to
match rac-core; CI runs ruff, mypy, and the offline test-suite. Dogfoods
Lore via an LCON-keyed rac/ corpus.
… seam)

ADR-001 fixes lore-connectors as a Python package matching the RAC
ecosystem. ADR-002 fixes the shared, outbound-only push seam — one module
per backend (rac-core ADR-073). Both validate under rac validate rac/.
…ry connector

Reads a 'rac export --documents' JSON Lines stream and upserts each record
into Supermemory, idempotent on the canonical id (custom_id) so a re-push
updates rather than duplicates. Outbound only — no pull, re-rank, or route;
no embeddings here (rac-core ADR-002, ADR-066). Auth via SUPERMEMORY_API_KEY;
--dry-run previews without an API call. The lore-connect CLI wires stdin or
--input to the connector.

Implements the corpus-export-shape-contract / lore-supermemory-interplay
designs in rac-core.
…rmed-line guard

Drives a fake Supermemory client — no live API in CI. Covers record->add
mapping, idempotent re-push on id, dry-run making no call, env-auth guard,
and malformed/blank-line handling. Fixture captured from a real rac export.
Explains the fuzzy-recall/verify-in-Lore loop, the Supermemory usage and
flags, the export contract consumed, and how a new backend slots in.
Adopt the rac-core house style: centered nav, badge row, tagline, and the
same section headers where they map (How it compares, Quickstart, Install,
How it works, Python API, Who it's for, Documentation, Origin, Repository
layout, Test, Project status, License).
Vendor the Lore header (light/dark) from rac-core under rac/assets/images/
and wire it into the README via a prefers-color-scheme <picture>, matching
the rac-core masthead.
Verified SdkSupermemoryClient against the real supermemory SDK (v3.48.0):
client.add(content, container_tag, metadata, custom_id) with metadata typed
str|float|bool|list[str] (so the export's aliases/tags lists are accepted)
and an AddResponse carrying id/status. Adds a stubbed-SDK test of the adapter
so the shape can't silently drift, and pins the extra to the verified v3
major.

Note: no live network round-trip — exercised against a stub, not a real key.
Adopt setuptools-scm so the version comes from the git tag (vX.Y.Z), matching
rac-core. Add python-publish.yml: on a published GitHub Release, gate on the
reusable CI workflow, build sdist+wheel, and publish to PyPI via trusted
publishing (OIDC, no token). CI checkouts fetch full history for scm.
…kage model

Add a PyPI/from-source Install section (the name is reserved, pre-release
installs come from the repo), a 'Run it in CI' GitHub Actions example, and a
'One package, many backends' section: backends are CLI subcommands with
optional per-provider extras, not separate packages (ADR-073, ADR-002).
The what/why of consuming rac export --graph and loading Lore's validated
relationship graph into a graph backend (Neo4j first). Companion to the
documents target already shipped.
…[roadmap:graph-connector]

The how: typed node/edge reader, a sibling push_graph seam beside the
documents push, MERGE-on-id idempotency, and the undirected/unresolved edge
handling. Implements rac/designs/graph-connector-shape.md.
…ap:graph-connector]

Locks the node/edge push seam, Neo4j as the first graph backend, MERGE-on-id
idempotency, undirected-as-single-edge, and skip-unresolved. Validated under
rac validate rac/.
…graph-connector]

Parse rac export --graph into typed Graph/GraphNode/GraphEdge dataclasses, and
add a sibling push_graph(graph) seam beside the documents push. Additive — the
documents Connector, reader, and CLI are unchanged. Implements
rac/designs/graph-connector-shape.md (ADR-003).
…p:graph-connector]

MERGE nodes by id and edges by type for idempotency; undirected edges written
once, unresolved edges skipped (no phantom nodes); Cypher fully parameterised.
Driver behind a thin client (env auth: NEO4J_URI/USERNAME/PASSWORD), optional
[neo4j] extra. Exposes 'lore-connect neo4j' with --dry-run/--input.
…roadmap:graph-connector]

Drives a fake driver — no live Neo4j in CI. Covers node/edge->MERGE mapping,
idempotent re-push, skip-unresolved, dry-run, parameterisation, the stubbed-SDK
driver adapter (env creds), and the CLI subcommand.
…raph-connector]

Add the Neo4j section, the [neo4j] extra, the --graph contract shape, a graph
Python API example, and frame both shipped targets (documents + graph).
Each connector documents itself once in docs/connectors/<backend>.md; a small
stdlib generator (scripts/sync_readme.py) stitches those into collapsible
<details> sections in the README's Connectors region, rewriting page-relative
links to the repo root. So a reader gets every connector on one page while each
connector owns its own file (no cross-PR README conflicts). A CI drift-guard
(sync_readme.py --check) fails if a page is edited without re-syncing. Migrates
the Supermemory usage into its page as the first one.
… pages pattern)

Adopt the generated-pages structure from main: drop the inline README edits
(including the --graph contract and graph Python API, which now live on the
page) and document Neo4j in docs/connectors/neo4j.md, then regenerate the README
Connectors region.
feat(neo4j): add the graph connector for the --graph projection
…nds] (#3)

* docs(decisions): record ADR-004 (Mem0 documents backend, resync idempotency)

Mem0 reuses the documents push(records) seam; it has no per-record upsert key
(verified against mem0ai 2.0.7), so idempotency is a container resync — clear
the source partition, then add. infer=False stores text as-is. Validated under
rac validate rac/.

* feat(mem0): add the Mem0 documents connector and CLI subcommand

Reuse the documents seam: map source->Mem0 user_id partition, ship text +
metadata (lore_id/type/status/title) with infer=False. Idempotent by container
resync (clear partition, then add). Driver behind a thin client (env auth
MEM0_API_KEY), optional [mem0] extra. Exposes 'lore-connect mem0'.

* test(mem0): cover record mapping, resync idempotency, dry-run, auth guard

Drives a fake client — no live API in CI. Covers record->add mapping with
lore_id metadata, clear-once-then-add, idempotent re-push (partition holds the
same set), dry-run, the stubbed-SDK adapter (infer=False, env key), and the CLI.

* docs(readme): document the Mem0 documents backend

Add the Mem0 section, the [mem0] extra, and frame both documents backends
(Supermemory + Mem0).

* docs(mem0): move usage into docs/connectors/mem0.md (align with the pages pattern)

Adopt the generated-pages structure from main: drop the inline README edits and
document Mem0 in its own docs/connectors/mem0.md, then regenerate the README
Connectors region. No conflict surface beyond the generated block.
…s] (#4)

* docs(decisions): record ADR-005 (Zep documents backend, graph-resync idempotency)

Zep reuses the documents push(records) seam; it has no per-record upsert key
(verified against zep-cloud 3.23.0), so idempotency is a graph resync — delete
and recreate the source graph, then add text episodes. Validated under rac
validate rac/.

* feat(zep): add the Zep documents connector and CLI subcommand

Reuse the documents seam: map source->Zep graph_id, add each record as a
type=text episode with metadata (lore_id/type/status/title). Idempotent by
graph resync (delete+create the graph, then add). SDK behind a thin client
(env auth ZEP_API_KEY), optional [zep] extra. Exposes 'lore-connect zep'.

* test(zep): cover record mapping, graph-resync idempotency, dry-run, auth guard

Drives a fake client — no live API in CI. Covers record->episode mapping with
lore_id metadata, clear-once-then-add, idempotent re-push, dry-run, the
stubbed-SDK adapter (delete+create, tolerates a missing graph), and the CLI.

* docs(readme): document the Zep documents backend

Add the Zep section, the [zep] extra, and frame both documents backends
(Supermemory + Zep).

* docs(zep): move usage into docs/connectors/zep.md (align with the pages pattern)

Adopt the generated-pages structure from main: drop the inline README edits and
document Zep in its own docs/connectors/zep.md, then regenerate the README
Connectors region.
…kends] (#5)

* docs(decisions): record ADR-006 (Letta documents backend, archive-resync idempotency)

Letta reuses the documents push(records) seam; a corpus source maps to a Letta
archive, and the connector resolves the opaque archive_id behind the client.
No per-record upsert key (verified against letta-client 1.12.1), so idempotency
is an archive resync. Validated under rac validate rac/.

* feat(letta): add the Letta documents connector and CLI subcommand

Map source->Letta archive; add each record as a passage with metadata
(lore_id/type/status/title). Idempotent by archive resync (delete archives by
name, create, add). Adapter hides the archive_id indirection; env auth
(LETTA_API_KEY cloud or LETTA_BASE_URL self-hosted), optional [letta] extra.
Exposes 'lore-connect letta'.

* test(letta): cover record mapping, archive-resync idempotency, dry-run, auth guard

Drives a fake client — no live API in CI. Covers record->passage mapping,
clear-once-then-add, idempotent re-push, dry-run, the stubbed-SDK adapter
(archive list/create/delete + passage create by resolved id, cloud and
self-hosted auth), and the CLI.

* docs(readme): document the Letta documents backend

Add the Letta section (cloud + self-hosted auth) and the [letta] extra.

* docs(letta): move usage into docs/connectors/letta.md (align with the pages pattern)

Adopt the generated-pages structure from main: drop the inline README edits and
document Letta in its own docs/connectors/letta.md, then regenerate the README
Connectors region.
…ackends] (#6)

* docs(decisions): record ADR-007 (Cognee documents backend, two-phase pipeline)

Cognee is the odd backend: a module-level async add->cognify pipeline with
native content-hash idempotency (incremental_loading), no per-record metadata
filter, verified against cognee 1.2.0. The connector stages records then
cognifies once per dataset; provenance rides in a Lore-Id header. Validated
under rac validate rac/.

* feat(cognee): add the Cognee documents connector and CLI subcommand

Map source->Cognee dataset; stage each record (with a Lore-Id provenance
header) then build the graph once per dataset via add+cognify. Idempotency is
Cognee's native content-hash dedup, not a resync. Async pipeline run behind a
thin client (env auth LLM_API_KEY, lazy import), optional [cognee] extra.
Exposes 'lore-connect cognee'.

* test(cognee): cover stage-then-commit, provenance, dedup, dry-run, auth guard

Drives a fake client and a stubbed async cognee module — no pipeline in CI.
Covers stage-per-record + commit-once, the Lore-Id provenance header,
content-hash dedup on re-push, empty-push no commit, dry-run, the batched
add+cognify adapter, and the CLI.

* docs(readme): document the Cognee documents backend

Add the Cognee section (two-phase pipeline, content-hash idempotency, the
no-deletion-prune caveat) and the [cognee] extra.

* docs(cognee): move usage into docs/connectors/cognee.md (align with the pages pattern)

Adopt the generated-pages structure from main: drop the inline README edits and
document Cognee in its own docs/connectors/cognee.md, then regenerate the README
Connectors region.
…he cross-repo dependency)

Adopt CalVer (YYYY.M.<minor>, independent cadence — not lock-step with
rac-core). Capture the real cross-repo dependency as the export contract
schema_version, checked in code, never a rac-core package pin (ADR-007,
ADR-063). Validated under rac validate rac/.
Add SUPPORTED_CONTRACT_VERSION ("1") and check_contract_version: the documents
and graph readers warn (ContractVersionWarning, on stderr) on an unknown
contract major and still proceed best-effort. The connector depends on the
contract version, not the rac package version (ADR-008).
…version

Update the setuptools-scm note for CalVer (tag 2026.6.1, not 2026.06.1 — PEP 440
strips the zero), and note the schema_version-1 target in the README export
contract section.
The version comments in pyproject.toml and python-publish.yml still carried
the SemVer-era 'tag vX.Y.Z' guidance, which wrongly implies a leading 'v' and
contradicts the CalVer decision. The PyPI publish triggers on a published
GitHub Release (no tag-pattern filter), and setuptools-scm strips a leading
'v', so no 'v' is required; the tag is YYYY.M.<minor> (e.g. 2026.6.1).

Comment-only change; no behaviour, build, or contract change.

Implements rac/decisions/adr-008-calver-and-contract-version.md.
…ap:rac-connectors]

Implements rac/roadmaps/repo-topology/rac-connectors.md (ADR-092).

Seeds the rac-connectors repository from the former lore-connectors with
history preserved, and applies the rac-* naming:

- distribution lore-connectors -> rac-connectors (registered on PyPI)
- import package src/lore_connectors -> src/rac_connectors (one dist, one
  subdir per integration: cognee, letta, mem0, neo4j, supermemory, zep)
- CLI entry point lore-connect -> rac-connect

The export-contract field names (lore_id) and the "Lore" product brand are
unchanged. Connectors remain thin export-contract consumers over the public
rac CLI; no engine internals (ADR-073, ADR-063, ADR-002).
…:rac-connectors]

Implements rac/roadmaps/repo-topology/rac-connectors.md (ADR-092).

Renames the outbound contract field the connectors write into backends:

- metadata key lore_id -> rac_id (mem0, letta, zep, supermemory)
- cognee header Lore-Id: -> Rac-Id:

The value is unchanged (the canonical RAC-* artifact id), so name and value
now agree (rac_id: RAC-...). This is a deliberate outbound data-contract
change, recorded in the rac-core ADR for the connectors repackage. The
"Lore" product brand and the verify-in-Lore loop wording are unchanged.
@tcballard
tcballard merged commit 85feffe into main Jun 29, 2026
4 checks passed
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