Skip to content

feat(reins): knowledge base isolation — every base answers only for itself (CLEAN-48) - #44

Open
maksymhryzodub-prog wants to merge 11 commits into
mainfrom
feat/CLEAN-48-knowledge-workspaces
Open

feat(reins): knowledge base isolation — every base answers only for itself (CLEAN-48)#44
maksymhryzodub-prog wants to merge 11 commits into
mainfrom
feat/CLEAN-48-knowledge-workspaces

Conversation

@maksymhryzodub-prog

@maksymhryzodub-prog maksymhryzodub-prog commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements CLEAN-48 — the knowledge-workspaces research outcome: a knowledge base becomes a real isolated area instead of a label on a shared pool, and the module stops needing a briefing.

  • Isolation (US1): one LightRAG instance per base, provisioned through the same Argo path as agent pods (reins/instance sub-slice mirroring workflow; image pinned by digest; slot-sized requests). Query, graph and entity list are base-scoped; a migrated base never falls back to the shared pool — a down instance is a stated 503, not silently borrowed content. Empty/no-coverage bases return answer: null, reason: no_relevant_content instead of a generated answer. References resolve to Source rows (file_source carries the source id). The agent tool lists only bound bases, refuses unbound ids, attributes every block, and names unreachable bases. SC-001/SC-002 are executable Jest specs.
  • Transition: one-time resumable per-base re-index (reins/migration) rebuilt entirely from Ranch's own storage — the operator supplies nothing. Reads stay on the shared pool until a base flips to done; the shared deployment remains the rollback until decommission (deliberately deferred, gated on every base migrating).
  • Finding bases (US2): server-side searchable, paged list with per-base context (sources, size, state); the agent screen edits bindings in place, marks template inheritance, and surfaces bindings to deleted bases instead of silently dropping them.
  • Clarity (US3): entityTypes/relationshipTypes removed from schema and contract (never sent anywhere in the product's history); retrieval tuning folded behind a disclosure with trade-off copy; the base header shows what it holds and whether it can answer.
  • UI defects (US4/US5): active tab fixed via NuxtLink custom slot (root cause: two utilities setting the same property at equal specificity); /knowledges/:id lands on Sources; the entity picker is a virtualized reka-ui combobox over the base-scoped labels endpoint with server-side search.
  • Honest status (US6): indexStatus derived from per-source states (empty/indexing/partial/ready); the misleading indexed boolean removed; per-source failure reasons with a single-source retry endpoint.

Spec, plan, research, contracts, task list and a verification log live in specs/007-knowledge-workspaces-research/.

Test plan

  • 182 Jest tests green (21 suites): manifest builder, routing policy, isolation integration (SC-001), adversarial tool set (SC-002), state mapping, readiness rollup
  • tsc --noEmit clean; OpenAPI regenerated into both consoles at every breaking step
  • Live HTTP run against the local stack (docker LightRAG + Ollama, mock provider): create → provision → ingest → queued→processing→indexed via track_status → query answers with resolved reference; empty base refuses without touching retrieval; scoped label search; reindex 202; derived rollup
  • emptyDir sufficiency proven live (both working dirs 0 bytes through ingest; query answers after restart with empty dirs)
  • Cluster run of quickstart scenarios 1–3 and 8 with the Argo instance provider (local mock cannot reproduce isolation by construction — stated in quickstart.md)
  • Manual browser click-through of the admin screens (SSR compiles all routes; API behavior behind each screen verified live)
  • T045 decommission of the shared pool — operational step after every base reaches migrationState: done on the live installation

🤖 Generated with Claude Code

maksymhryzodub-prog and others added 11 commits August 27, 2026 12:59
Current-state audit of the knowledge module and the specification built on
it. The audit's central finding: retrieval isolation does not exist. The
workspace namespace is attached to writes only, the retrieval service binds
it at process start and none is configured, so every base answers from one
shared pool and the graph describes the whole installation.

The product owner settled the open scope question on 2026-08-27: Ranch is
personal, and an agent given one base must neither read nor inspect another.
That reversed two earlier decisions -- the isolation boundary is the
knowledge base rather than a container above it, and the transition needs a
one-time re-index because the shared pool cannot be split after the fact.
The re-index costs the operator nothing: every source type is rebuildable
from Ranch's own storage.

36 requirements, 14 success criteria, 6 prioritised stories. Ready for
planning, which owes an arrangement for running one retrieval process per
isolated base.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SErhdDayRqyC2hRhmFvLnf
Phase 0 research and Phase 1 design for making a knowledge base a real
isolated retrieval area.

The research finding that shapes the plan: an isolated instance per base is
not a new capability for ranch but a second manifest builder. The platform
already provisions a pod per agent through Argo, already watches those pods,
and already reports free cluster slots. Sized as an agent slot (100m CPU,
512Mi, Burstable) rather than as the shared instance's 500m/1Gi, ten bases
reserve 1 CPU and 5Gi -- which is what makes per-base isolation affordable
after it was rejected on footprint.

Alternatives are recorded with why they lost, including a custom Python
service holding many LightRAG instances in one process, kept as the
documented escape hatch if pod count becomes the binding constraint.

Artifacts: research.md (R1-R10, no unknowns left), data-model.md,
contracts/knowledge-api.md, contracts/retrieval-instance.md, quickstart.md.
Three items are flagged for verification on dev, each with a fallback; the
load-bearing one is whether emptyDir replaces the per-instance PVCs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SErhdDayRqyC2hRhmFvLnf
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…n (CLEAN-48)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ing (CLEAN-48)

Phase 1+2 of knowledge base isolation: instance gateway mirroring the
workflow slice (Argo/mock/router, manifest builder with unit spec, pinned
image digest), per-base LightRAG routing with migration-aware policy,
instance lifecycle on base create/delete, startup reconciliation, and the
schema fields (instanceState, migrationState, per-source indexState).
emptyDir sufficiency verified live; shared pool still serves all reads.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…umable migration (CLEAN-48)

US1: queries answer only from the asked base's instance (no_relevant_content
instead of generated answers from no context), graph endpoints become
/knowledges/:id/graph[/labels] with api-side search, references resolve to
Source rows via file_source ids, the agent tool attributes per base and
refuses unbound ids, per-source indexState is driven from track_status, and
a resumable per-base re-index moves content off the shared pool. SC-001 and
SC-002 are executable Jest specs (31 tests); contract regenerated into both
consoles.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…with context (CLEAN-48)

US2: GET /knowledges becomes a paged envelope with search (name, description,
source names) and per-item context (sourcesCount, totalSizeBytes); admin list
searches server-side and pages; the agent knowledge tab edits bindings in
place, marks template-inherited lists, and surfaces bindings to deleted bases
instead of silently dropping them; binding pickers show what each base holds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… header (CLEAN-48)

US3: entityTypes/relationshipTypes dropped from schema, contract and both
consoles (never sent anywhere in the product's history); query tuning
controls fold behind a disclosure with defaults that answer unaided, each
stating what it trades; opening a base shows what it holds and whether it
can answer without further navigation; graph demoted to the last tab as an
inspection surface; empty states name the next action.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ker (CLEAN-48)

US4: tabs bind exactly one class set from NuxtLink's custom-slot isActive
(the old two-utility conflict was decided by stylesheet order and never
highlighted); /knowledges/:id lands on Sources instead of an empty body.
US5: the entity picker becomes a reka-ui virtualized combobox fed by the
base-scoped labels endpoint with server-side search capped at 200, and it
distinguishes "no entities yet" from "no match".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…e-source retry (CLEAN-48)

US6: indexStatus is derived from source states (empty/indexing/partial/ready)
instead of asserted — a base can no longer read ready while nothing is
searchable; the misleading `indexed` boolean is removed from the contract;
POST /knowledges/:id/sources/:sourceId/reindex retries one failed source
without touching the batch; the admin sources table shows each source's own
state and failure reason with a retry action, polling while processing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…n (CLEAN-48)

46/47 tasks done; T045 (shared-pool decommission) deferred — operational,
gated on every base reaching migrationState done on the live installation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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