KVS as a concurrent + AI-first forge — the server/host face of Koder Version System
One line. Make KVS = Koder Version System the end-to-end version system — keep its existing clientengine face, and add a *erverhost face (the next-gen forge, Koder-Flow's successor) whose differentiators are (1) conflict-free concurrent writes for fleets of AI agents and (2) an AI-first/MCP surface co-equal to git+web — on a recursive namespace tree*over kdb-next + kdb-obj.
0. Status & relationship to prior art
This RFC is not greenfield. It extends stack-RFC-006 §5 (the concurrent VCS layer, jj-style, which already named products/dev/kvs as the home) and the already-decided object plane (§3/§7, owner-ratified 2026-06-10: BUILD kdb-obj). It inherits rather than re-derives:
- refs on kdb — DONE as a primitive (FLOW-147 spike PASS + FLOW-148
productionize + #156-165). Single-statement CAS = exactly-one-winner under concurrency (the concurrency keystone). Shadow-write in Flow today.
- kdb-obj object plane — owner-ratified to build (RFC-006 §7 +
infra/data/ossADR-001, 2026-06-08: compose
s3s+reed-solomon-simd+ kdb metadata behind a swappableObjectEnginetrait). It is its own componentinfra/data/oss(the object-storage substrate under the kdb family), NOT kdb core. Build is already underway: OSS-007 done (crate skeleton + ObjectEngine trait); OSS-008-011 pending (s3s API + Koder ID auth/RLS · reed-solomon EC placement + kdb meta · OSS-010 wires the first consumers = FLOW-148 git objects + Hub depot · OSS-011 drives the self-hosted-pairs row-18 G1→G5 gates / MinIO flip). Flow'smodules/kdb_obj/is a stub consumer awaiting OSS-010. - KVS engine pieces — KVS#179 conflict-as-data, KVS#180 virtual-branch-cli,
KVS#184 cross-link, KVS#202 concurrent-commit + provenance trailers.
- kdb building blocks — kdb#542 BlobRef column type, kdb#733 blobref cascading
delete, kdb#717 WAL bottomless S3 archive tier.
What this RFC changes vs RFC-006 §5: §5 split the work as *KVS = client/engine, Flow = host. The owner's direction (2026-06-10) makes *KVS the host too*— the forge that supersedes Flow. This RFC reconciles that shift: KVS absorbs the host role; Flow becomes the legacy host we migrate off (§9).
1. Motivation — the real drivers
The motivation is not the residual gitea strings in Koder Flow (those are deliberate fork-residue — license headers, upstream imports, the .gitea/ Actions path; the rebrand is DONE). The real, structural drivers are:
- Rigid 2-level data model. Gitea/Flow bakes
owner_id → repointo thousandsof queries. The owner wants an arbitrary namespace tree (a namespace contains namespaces and repos, any depth — GitLab-subgroup-like) which a fork cannot retrofit cheaply.
- Flow is an island. Own DB, own auth — not a Stack-native citizen. KVS-host
is kdb-native (data), Koder-ID-native (auth), Jet-served, KDS-skinned.
- The AI-concurrent regime. Git/GitHub assume humans serializing via PR. KVS
assumes most commits come from a fleet of AI agents editing concurrently at high frequency — the exact pain of N
/k-gosessions clobbering this monorepo today. That regime needs conflict-free concurrent writes + AI surfaces as first-class, not bolted on.
2. Decision 1 — build vs fork-extend (the host)
Decision: greenfield Koder-native host that EMBEDS git (does NOT rewrite git's core), reusing the KVS engine + the kdb durable tier. This is the Layer mechanism of RFC-006 §5.2 (new front-end + working-copy model over an intact git store; interop day 1, reversible), explicitly not the "Own engine" (E) last resort.
| Option | Long-term | Why not |
|---|---|---|
| Fork-extend Flow | Retrofit a namespace tree into Gitea's owner_id→repo schema |
The 2-level model is woven through thousands of queries (D9 migration cost is enormous; D1 wrong abstraction stays baked). Rejected. |
| Greenfield, rewrite git core (E) | Full control of the object model | Loses native git interop; "eternal liability" (RFC-006 §5.2 E). Rejected for v1; a Koda-native git is a north star, not a start. |
| Greenfield host embedding git (L) — CHOSEN | New data model (namespace tree) + UI + Stack-native, with git plumbing embedded (shell-out / go-git) and the durable tier on kdb refs + kdb-obj | Interop day 1; the hard solved part (smart-http/ssh, pack, LFS) is reused, not rebuilt; matches RFC-006 §5 strategy. |
Trade-off accepted (Quality > Speed, stack-principles §2): we pay the design + integration cost of a Stack-native host instead of the fast path of patching Flow, in exchange for the namespace tree + concurrency + AI surfaces being structurally correct (D1) rather than retrofitted onto the wrong abstraction.
3. Data model — the recursive namespace tree (the keystone)
The keystone, and the one thing a fork can't retrofit:
- A
namespaceis a recursive node: it may contain child namespaces andrepos, to arbitrary depth. There is no privileged "organization" level — "org", "team", "project", "personal" are all just namespaces with policies.
- Path = the namespace chain (
a/b/c/repo), resolved through the tree, not aflat
owner/repo. - Storage: the tree + repo metadata live in kdb-next (relational/tree
queries, MVCC); large immutable bytes (git objects/packs) live in kdb-obj (content-addressed); refs live in kdb (transactional CAS).
- Permissions resolve through the tree via Koder ID — inherited down the
chain, overridable per node. Multi-tenancy per
specs/multi-tenancy/contract.kmd(D5): cross-tenant access 404s;tenant_idon every row. - Moves/renames are cheap (re-parent a subtree) — vs Gitea's transfer pain.
Open question OQ-1 (§12): the exact tree-permission resolution model (inheritance + override + visibility) — needs its own spec section before implementation.
4. Concurrency model — conflict-first-class (Pillar 1)
Insight: git objects are immutable + content-addressed → writing an object never conflicts (same content → same hash, idempotent; different content → different hash, both stored). The only contention point is the mutable ref. So "extreme concurrency" reduces to making ref-advance non-blocking and auto-merging:
- CAS object store on kdb-obj — conflict-free by construction; inherits kdb's
apply-order-independent concurrent writes (kdb#790#791#792) + group-commit.
- Mergeable ref DAG, no locks — a branch is not "one SHA under CAS-lock";
concurrent pushes to the same branch trigger server-side AST/block merge (the KVS engine, KVS#179/#202) → both land, zero non-ff rejection. No per-repo / per-ref lock (the opposite of Gitea). The refs→kdb single-statement CAS (FLOW-148) gives the exactly-one-winner primitive the merge loop builds on.
- Conflict = explicit committable state, never silent corruption — when
auto-merge can't resolve, the result is a first-class conflict object (KVS#179 conflict-as-data / jj model) surfaced as a
needs-resolutionstate — not a rejection and not a silent overwrite. (We just lived the silent-.git/index-corruption pain; this contract is the antidote.) - Stateless host frontends + kdb shared concurrent data-plane → scale
frontends horizontally; concurrency lives in the data plane.
Acceptance bar (the differentiator): N agents concurrent-push the same branch → all land via server-side merge, 0 non-ff rejections, conflicts (if any) materialize as explicit conflict objects. This is the walking-skeleton keystone (§8) — prove it first.
Open question OQ-2 (§12): the precise "can't-auto-merge → conflict object" contract + how a merge driver is selected per file/language (RFC-006 §5.2 maps semantic merge to the Driver mechanism: per-language merge driver via
.gitattributes). This is the research-y core; the KVS engine is the head-start.
5. AI-first / MCP surface (Pillar 2)
MCP is a co-equal surface to git + web, not a plugin:
- Parity: every operation (namespacerepo read, file readedit, branch, PR,
comment, code search, diff, merge, conflict-resolve) is an MCP tool/resource. Port Koder Flow's MCP lessons (FLOW-094108178/192): resource hierarchy, scope-gated tools, per-token rate limit, cross-tenant 404.
- Agent identity is first-class (not only humans): scoped tokens + identity via
Koder ID / SVID; provenance on every op (KVS#202 trailers) → "which agent did what" auditable (D8).
- AST/block-level ops exposed — agents edit at the structural level (the same
engine as the merge) → semantic edits + clean merges (direct synergy with §4).
- Token-efficient structured APIs (diffsearchfile-read; the Koder IRIS
"10× fewer tokens" principle); conform to
stack-RFC-002-mcp-integration.
6. Git plumbing strategy
Embed, don't rewrite (RFC-006 §5.2 mechanism table). v1: shell-out to system git for smart-http/ssh + pack ops behind a thin server (proven; how Gitea does much of it), with go-git watch-listed for pure-Go paths. The durable tier is kdb refs (transactional CAS) + kdb-obj (objects/packs) — refs→kdb and objects→kdb move from Flow's shadow to KVS's primary (§11). A Koda-native git engine stays a north star (mechanism E), explicitly out of v1 scope.
7. Stack integration (reuse-first, D10)
| Concern | Reused Stack component |
|---|---|
| Auth / identity / agent tokens | Koder ID (OAuth/OIDC + SVID) |
| Relational/tree data + refs | kdb-next |
| Object/pack bytes (CAS) | kdb-obj (RFC-006 §3) |
| Serving / TLS / vhost | Koder Jet (policies/web-server.kmd) |
| UI tokens / theme | KDS / Verge |
| Multi-tenancy | specs/multi-tenancy/contract.kmd |
| Observability | 3-signal (policies/observability-first.kmd) |
| MCP conventions | stack-RFC-002-mcp-integration |
| Concurrent merge engine | the existing kvs client engine |
8. Phased plan + walking skeleton
Milestone 0 — walking skeleton (prove the bet cheaply). Acceptance: recursive namespace tree on kdb-next + Koder-ID auth + a repo you can git clone/push (objects on kdb-obj, refs on kdb) + N-agent concurrent push to the same branch all land via server-side merge (0 rejections) + a minimal MCP endpoint (read repo / read file / open branch) + minimal KDS UI. No issues/PR UI/CI yet — prove data model + git round-trip + concurrency + MCP + Stack integration end-to-end.
Then, feature-by-feature (each importing parity from Flow): browse/diff, PRs (with conflict-as-data), issues, code search, webhooks/Actions, packages, mirroring. Sequence detail lives in subsequent tickets, not this RFC.
9. Migration — Koder Flow → KVS
- Importer
Flow → KVSis a first-class requirement (Flow already has theinverse
gitea_migrationsdriver as a reference). - Coexistence, no big-bang: KVS mirrors/imports from Flow until parity;
cutover per repo/namespace when ready. KVS's host role supersedes Flow's RFC-006 §5 host role at cutover; Flow is decommissioned after.
- Per
policies/self-hosted-first.kmd, KVS-host vs Flow is a Koder-replaces-Kodersuccession — promotion gated on functional + regression parity.
10. Naming & registry
KVS = Koder Version System is the umbrella product spanning client (the existing concurrent working-copy CLIengine) and server (this forgehost). "Concurrent" is the differentiator, not a separate name. The forge lives inside products/dev/kvs/ as an RFC-006 sector (backend/ + app/web, alongside the existing cli), not a new top-level module. component-names.md row updates to expand the acronym + note client+server scope, via the audit-naming gate.
11. Dependencies & sequencing (foundational critical path)
kdb-obj substrate (infra/data/oss OSS-008-011, building) ──┐
├─► objects shadow→PRIMARY ──► KVS host stores repos 100% on kdb
refs→kdb (FLOW-148, exists shadow) ──► refs shadow→PRIMARY ──┘- kdb-obj substrate is the foundational dependency and is *lready an active,
independent build in
infra/data/oss(OSS-007 done; 008-011 pending) — its contract is layer-independent (content-addressed bytes; mergenamespaceprovenance live above it), so it serves Flow + Hub depot + model-weights regardless. No ticketization needed (they exist). KVS's stake: OSS-010*(the git-objects + Hub-depot consumer wiring) is the piece KVS-host consumes — track + co-design it so the consumer contract fits KVS-as-primary, not only Flow's shadow. - Flow left objects at stub and refs at shadow; *VS forces both to
primary*— that is the gate from "forge stores on filesystem" to "forge stores on kdb".
12. Open questions
- OQ-1 — RESOLVED 2026-06-10 →
specs/kvs/namespace-tree.kmd:recursive node model, nearest-ancestor-wins + explicit-deny resolution, monotonic visibility clamp, cheap re-parent moves, root=tenant boundary, agents as first-class subjects (R1-R7 + R-AI + T1-T7).
- OQ-2 — RESOLVED 2026-06-10 →
specs/kvs/concurrent-merge.kmd:objects-never-conflict + lock-free auto-merging ref advance, Driver-selected three-way (AST-aware), conflict-as-committable-object (never reject/overwrite), exactly-one-winner optimistic-bounded-retry on the FLOW-148 CAS, provenance per merge (R1-R7 + T1-T6).
- OQ-3 — namespace-aware object placement on kdb-obj (does the flexible tree
drive trust-tiering/placement policy? RFC-006's
ObjectEngineplacement vocabulary is the extension point). - OQ-4 — ActionsCI: keep `.giteaworkflows` compat for migration, or a
Koder-native concurrent CI surface? (out of v1 skeleton scope.)
13. Decision log
- 2026-06-10 — owner: KVS name unified (client + server), greenfield host embedding
git, concurrency + AI-first as first-class pillars.
/k-archdeliberation (this session) ratified RFC-first with the kdb-obj substrate parallelizable. This RFC is the durable form of that deliberation. - 2026-06-10 — owner RATIFIED this RFC (status: draft → ratified). KVS-host
program is GO. Per §8/§12 the next step is the OQ-1 (namespace permission model) + OQ-2 (mergeable-ref conflict-object contract) spec sections, then the walking skeleton. kdb-obj substrate (
infra/data/ossOSS-008-011) building in parallel; KVS's stake = OSS-010's consumer contract.