# AGS Removal Architecture

> Canonical path: `specs/architecture/ags-removal.md`
> Status: living migration architecture
> Scope: replacing the embedded Agent Git Service subsystem, its protocols, and
> its persistence ownership with the native AgentTeam Content Store.

## Decision

AgentTeam removes AGS as a product and persistence subsystem. This is not a process
or routing cleanup: AGS currently owns versioned content, Git protocol,
repository authorization, events, and historical state used by Knowledge Base,
Skill, Memory, Role, Automation, Web, and Desktop.

The target architecture has three ownership layers:

1. **Content Store** is the common service boundary and owner of
   `VersionedContent` identity, immutable tree `ContentVersion` records, remote
   head compare-and-swap, history, events, and retention. Its payload backend
   does not own a second version protocol.
2. **Product domains** own metadata, authorization, client behavior, opaque
   `ContentVersion` references, and the dedicated migration store that maps
   their legacy identities to native versions. They select capabilities from
   the product contract, never choose a backend per request, leak AGS identity
   into Content Store contracts, or mutate Content Store persistence directly.
3. **External Git integration** is a bounded import or mirror client. AgentTeam no
   longer acts as a Git server or exposes a GitHub-compatible repository
   product.

AgentTeam does not preserve AGS by renaming its package or hiding its handler behind
another facade. GitHub-compatible REST, GraphQL, Git Smart HTTP, AGS identity,
collaborators, repository access tokens, AGS Wiki, issues, pull requests,
labels, and releases are retired after their product callers and retained data
have migrated.

## Plain-language outcome

AGS is an embedded Git service that currently sits between AgentTeam products and
their content. Removing it means that AgentTeam itself owns the content identity,
immutable versions, permissions, and events that those products need. Users
keep creating, reading, sharing, and restoring product content, but they no
longer depend on an internal repository, branch, commit, repository token, or
Git event to do so.

The migration follows one end-to-end path:

1. Each product stores and opens an exact immutable `ContentVersion`, so a
   history entry, citation, backup, or run always resolves the bytes it
   originally referenced even after the current head advances.
2. The owning product rechecks live membership and grants at every native
   access boundary. Revoked users, grants, or resources fail closed; cached
   repository credentials and stale mappings cannot preserve access.
3. Required AGS history is imported with explicit target, file, byte, time,
   concurrency, and retry bounds. A bounded full import plus one best-effort
   delta observation may omit a small number of legacy writes accepted during
   deployment; AgentTeam does not build dual-write, writer-drain, or lossless
   rollback machinery solely to close that window.
4. A related product family switches only after its content, references,
   permissions, and callers are ready together. Authority changes once from
   implicit legacy ownership to one exact native binding; partial activation
   and native-to-AGS fallback are forbidden.
5. After every active caller is native, AgentTeam deletes AGS routes, protocols,
   credentials, authorization state, workers, event bridges, schema, payload
   roots, and module dependencies. External Git may remain a bounded import
   source, but never an internal source of truth.

The product migration families are deliberately independent where ownership
allows it: Knowledge Base and its Q&A, browser, Wiki, and analysis surfaces;
Automation with its Activity and event lifecycle; cloud Memory versions and
checkpoints; and the already separated Role and Skill owners. They share the
Content Store contract, but each family owns its live authorization, bounded
import, derived projections, cutover decision, and removal of its AGS callers.

## Current state

The runtime topology is already unified: `agentteam-server` owns the resident MeshX
runtime and there is no standalone MeshX or AGS process, image, listener, or
discovery path. That topology change did **not** remove the AGS subsystem.

The active embedded subsystem still includes:

- `internal/resource/server` constructing
  `github.com/pingcap/agent-git-service/server`, starting its workers, including
  it in readiness and shutdown, and attaching repository event bridges;
- public and forwarded `/api/v3/**`, `/api/ext/v1/**`, `/api/graphql`, raw file,
  global AGS, and `/{owner}/{repo}.git/**` Smart HTTP surfaces;
- AGS-native authentication, repository credentials, collaborator
  materialization, internal workload identity, and repository access tokens;
- a separate `MESHX_AGS_DATABASE_DSN`, AGS schema lifecycle, and bare
  repository root configured by `MESHX_AGS_GIT_REPO_DIR`;
- Knowledge Base mirror/Wiki/Q&A, Memory, Skill, Role package, Automation,
  activity, and source-revision code that reads or writes AGS repositories or
  consumes AGS repository events;
- Web repository APIs and pages for GitHub-compatible repository features, and
  Desktop clone/fetch/push flows for Memory, Skill, and Knowledge Base content;
- the root module dependency and local replacement at `x/agent-git-service`.

The native Content Store foundation under `internal/contentpayload`,
`internal/store/content`, and `internal/service/content` provides
the tree payload contract, version/head metadata,
compare-and-swap publication, quota and pins, bounded outbox and GC workers,
exact-version reads, AGS-to-native migration tooling, and persisted writer
authority. The tree API/runtime exists only behind the default-off global
switch and an exact registered binding plus `native_active` authority. The
foundation stage opens only the tree payload backend when enabled: it registers
no generic HTTP capability, deployable test binding, or GC owner. Role and Skill
now register separate owning-domain adapters over the shared tree core, but a
binding remains under implicit AGS ownership unless its persisted exact
authority is explicitly `native_active`. New server-generated Role and Skill
IDs remain implicit legacy bindings; ordinary legacy reads and writes do not
materialize authority rows, and wildcard authority cannot capture future IDs.
The common foundation is therefore not a production write owner by itself, and
broad product cutover still requires bounded backfill, reference verification,
and an explicit per-binding transition.

Therefore the embedded AGS module and routes cannot be deleted from the current
state. Only standalone topology artifacts that have no callers may remain
absent; subsystem deletion is the final migration stage.

## Target ownership

```mermaid
flowchart LR
  C[Web / Desktop / agent callers] --> API[AgentTeam workspace APIs]
  API --> K[Knowledge Base]
  API --> S[Skill / Role]
  API --> M[Memory]
  API --> A[Automation]
  K --> R
  S --> R
  A --> R
  M --> MS[Memory local-first sync]
  MS --> R[Content Store]
  R --> DB[(MeshX DB\ncontent versions + outbox)]
  R --> ST[TreePayloadBackend]
  ST --> GIT[Internal bare Git payload engine]
  R --> O[bounded idempotent consumers]
  EXT[GitHub / GitLab / Gitea] --> I[bounded importer or mirror]
  I --> R
  K --> P[KB index / derived projections]
  R -. exact input version .-> P
```

The [Content Store Architecture](./content-store.md) is the
source of truth for common version ownership, the tree payload contract,
manifest/blob integrity, publication order, CAS, outbox, retention, and request
cost bounds. This spec owns domain semantics, consumer migration, protocol
removal, data backfill, one-way cutover, post-cutover recovery, and deletion
gates.

### Storage selection and native contracts

Every VersionedContent aggregate is a complete immutable tree stored through
`TreePayloadBackend`. Callers use only common tree operations; there is no
per-request backend/model choice or document payload contract.

VersionedContent has an opaque workspace-scoped ID, one monotonic revision, and
an optional immutable remote head. A ContentVersion contains model-specific
canonical payload metadata. Product code stores opaque
`versioned_content_id + content_version_id` references and cannot receive a
local path, bucket key, store model, or mutable payload.

All head-changing requests carry `expectedHeadVersionId` and a binding or
cutover generation. A stale head returns a conflict without losing uploaded
content; a stale generation rejects a client session created before an owner
change. Server-issued upload/download sessions are short-lived and scoped to
one workspace, VersionedContent aggregate, operation, and size limit. They do
not recreate a long-lived AGS repository token.

The native API provides only product-required common capabilities: create/get a
VersionedContent aggregate, list immutable versions, publish with expected
remote head, read a version, compare compatible versions, and observe events.
Tree/file/archive are tree-only capabilities. It does not expose Git branches,
clone URLs, pull requests, issues, releases, collaborators, or GitHub DTOs.

Memory is local-first. Desktop or the agent owns the live working set and a
durable local version journal plus sync outbox. Background sync publishes a
coalesced complete tree checkpoint with replica ID,
covered local sequence range, base remote version, binding generation, and
digest. The Content Store owns immutable cloud versions and the cloud head; it
is a remote backup/history and cross-device sync boundary, not the synchronous
owner of local edits. Every local edit remains in the local journal, but it does
not create one remote version.

The initial contract permits one active sync device per binding. A generation
change fences an old device from advancing cloud head without deleting its
unsynced local data. CAS or lineage conflict preserves both local and remote
content and requires explicit merge or recovery. Restoring a cloud version
materializes local state and creates a new local version; it never silently
rewinds the live working set.

Memory uses the canonical `memory_fileset_v1` full-snapshot codec and limits
defined by the Content Store Architecture. Delta is a transport optimization
only; no durable cloud version may depend on a missing base. History and
compare use the transactionally stored bounded path/digest summary and stable
cursors; they do not decode hundreds of full snapshots. The full snapshot
remains the independent restore source of truth.

Automatic cloud checkpoints coalesce the newest contiguous unsynced local
range, allow only one in flight per binding, and start no more frequently than
once every five minutes. Continuous edits update the pending checkpoint without
postponing its next eligible attempt. The initial binding quota is 512 retained
versions, 1 GiB of stored tree bytes including manifests and blobs,
and 64 backup labels or explicit pins. The current head and every
pinned/product-retained version count against quota and are never automatically
deleted. If bounded pruning of old unpinned checkpoints cannot create admission
room, sync returns quota backpressure while preserving local content, journal,
and outbox.

AGS migration retains, for every active Memory binding, the bound branch's
first-parent history from the oldest reachable commit through head; every
explicit backup tag target; and any commit directly referenced by product
state. Each retained commit is normalized to a full `memory_fileset_v1`
snapshot. The `ContentVersion` parent follows the preceding imported
first-parent commit. A
backup target outside that chain is imported as an immutable version linked to
its nearest retained imported ancestor when one exists, without advancing cloud
head. Git author, time, and message remain source metadata; branches, merge DAG,
and tags do not become native version-control primitives.

Other branches and unreachable commits are excluded only after the preflight
inventory proves that no active binding, backup label, or product reference
needs them. Preflight computes retained version, payload-byte, and pin totals
before writing. A retained history over the configured finite quota blocks
migration until an operator-approved capacity allocation is applied; it is not
truncated. Any retained commit containing an invalid path, normalization
collision, non-text/binary content, symlink/special entry, or over-limit
snapshot likewise blocks that Memory migration. The backfill never skips,
truncates, or silently converts such content to the tree model.

### Domain references

The stable target is explicit domain ownership rather than a generic
`resource_repositories` compatibility table:

| Domain | Native reference and behavior | AGS behavior removed with migration |
| --- | --- | --- |
| Skill | Skill stores its active exact content/version; immutable SkillVersion rows drive native import, read, bounded history, backup, restore, rollback, and agent projections without repository tokens | repository initialization, clone/backup, Git refs for each activated binding |
| Role | RoleVersion and each manifest item store exact content/version/path; native reads validate that projection before opening payload | hidden AGS package repository and path reads for each activated binding |
| Knowledge Base | each source revision references a ContentVersion or an immutable external revision; index/derived Wiki records their exact inputs | source mirror AGS repository, AGS Wiki, Git primitives in Q&A |
| Memory | local working set and journal are authoritative; Memory sync asynchronously publishes bounded tree ContentVersions and tracks local-version↔cloud-version acknowledgements | per-agent clone remote, branch, AGS credential and push |
| Automation | definition is `versionedContentId + contentVersionId + path`; publish creates a version; outbox drives runs and activity | archive/checkout/status/push-event and Wiki/tree publication through AGS |
| Activity | idempotent outbox consumers project ContentVersion events | process-local AGS repository event sinks |

A domain migrates only when its native reader, writer, authorization, history,
client, and event behavior all use the Content Store and its declared domain
contract. Each migration removes the replaced AGS helper and compensation path
in the same change; it must not leave a permanent dual stack.

## Migration invariants

The following rules apply throughout the migration:

1. **One forward authority switch.** AGS remains authoritative until one exact
   product binding switches to the Content Store. The switch does not require
   AGS writer drain, cross-system dual write, or a quiescent source. Writes
   accepted by AGS after the final best-effort observation but before the exact
   binding's legacy mutation cutoff may be absent from the native lineage. Once
   the cutoff and switch complete, every product read and write uses the Content
   Store, stale AGS mutations fail closed, and a native failure never falls back
   to AGS.
2. **Exact observed source identity.** Every selected legacy revision is keyed
   by `ags_repository_id + commit_sha`; its mapping records the ContentVersion,
   content model, and verified digest. The importer reproduces the selected
   revision exactly, but it does not guarantee capture of a later AGS revision
   created during the deployment window.
3. **Bounded work.** Export, reference backfill, verification, outbox
   consumption, and GC use explicit batch/file/byte/time limits and cursors.
   Request paths never scan all workspace `VersionedContent` aggregates or an
   object-store prefix.
4. **Payload before references.** Tree objects/manifests are staged and verified,
   before a DB transaction publishes a version or changes a product reference. Unreferenced
   tree objects remain on the GC ledger; they are not synchronously deleted
   after an ambiguous DB acknowledgement.
5. **Authorization stays in the product owner.** Every native request checks
   workspace scope and the owning domain ACL. Opaque IDs and storage paths are
   not authorization.
6. **No silent compatibility.** A migrated caller cannot fall back to AGS after
   a native error. Compatibility readers, when temporarily required for
   unmigrated bindings, are selected by explicit migration state and have a
   deletion gate.
7. **No reverse AGS authority rollback.** A deployment may be aborted before
   native writes begin. After native writes begin, code rollback must remain
   compatible with the Content Store or the system must be forward-fixed. AGS
   is retained temporarily as read-only evidence, not as a lossless write
   rollback target.

### Accepted legacy-write loss boundary

The migration deliberately accepts a small recovery-point objective gap for
legacy writes during deployment. Each domain performs one bounded historical
backfill and one best-effort delta observation immediately before its authority
switch. The interval between that observation and the exact binding's legacy
mutation cutoff is the **legacy-write loss window**. A write accepted only by
AGS in that window may be omitted from Content Store history.

The cutoff is a required part of the one-way cutover, not deferred subsystem
cleanup. The product owner enforces it immediately before native activation, or
as the first action of the same ordered cutover step, by revoking or failing
closed every ingress and credential that can mutate the exact legacy binding.
This includes general AGS REST and GraphQL routes, Git Smart HTTP receive-pack,
repository tokens, and stale Web/Desktop or service clients when they target
that binding. Native activation cannot succeed until the cutoff is proven. Work
already accepted by AGS before the cutoff may finish without being imported;
every mutation presented after the cutoff is rejected even while those shared
protocols remain available to unmigrated bindings.

This trade-off removes cross-system dual write, writer drain, final-quiescence
loops, reverse synchronization, and target-side receipt/replay machinery. The
cutoff does not wait for already accepted requests to drain. The deployment
records the observation, cutoff, and activation times plus any late-write count
available from existing AGS reads. The count is diagnostic evidence, not a
reconciliation queue. A domain with an unacceptable observed gap aborts before
native writes begin; it does not extend AGS with a new durable migration
platform.

The accepted loss applies only to writes that remain on the legacy AGS path.
Once the native owner is active, Content Store data retains its normal CAS,
durability, authorization, quota, and recovery guarantees.

### Existing implementation convergence

Code written under a stronger lossless-cutover assumption must be reclassified
against this contract before additional domain cutovers build on it:

- keep permanent Content Store capabilities, including immutable versions,
  authorization, expected-head CAS, quota, native outbox/GC, bounded product
  importers, product-owned legacy-to-native mappings, and digest verification;
- keep native-domain crash and retry guarantees after the Content Store owns a
  binding;
- remove cross-system dual-write, AGS writer-drain/final-catch-up fencing,
  reverse synchronization, and AGS-side receipt/replay/projection/GC machinery
  whose only purpose is lossless legacy cutover or rollback to AGS;
- prefer existing AGS reads. Any new AGS migration endpoint must be internal,
  read-only, bounded, and necessary to obtain one immutable source revision. It
  must not become a generic product API or background runtime.

This convergence is delivered separately from new product-domain integration
so deletion and behavior changes remain reviewable. It must not absorb
unrelated refactors or weaken permanent native data guarantees.

## Delivery plan: three phases

The migration uses three product phases with independently reviewable delivery
units. A unit can be aborted before its native authority switch; after native
writes begin it is not reversible to AGS. Inventory, backfill tooling, and
runbooks are part of these stages; they are not separate long-lived projects.

### Phase 1: implement the Content Store

The **foundation stage** completes the production-capable common boundary
without moving a production writer. It includes:

- a reproducible inventory of AGS imports, routes, configuration, schema,
  protocols, clients, readers, writers, events, credentials, and data owners,
  plus a ratchet that rejects new coupling;
- one tree model, `TreePayloadBackend`, and canonical Memory tree validation;
- workspace/domain authorization, the narrow native API, scoped sessions,
  expected-head CAS, binding generation, and idempotency;
- transactional outbox delivery, tree GC, Memory checkpoint coalescing,
  indexed path/digest summaries, finite quota/retention, and explicit
  backpressure;
- legacy commit mapping plus bounded import/backfill/verify primitives owned by
  AgentTeam product domains, progress ledgers, and the one-way cutover runbook. AGS
  itself gains no generic receipt, replay, projection, GC, or cutover worker.

The Content Store remains inactive for product writes after the foundation
stage. No caller silently selects it and no AGS path delegates to it as a
fallback.

**Gate:** storage, codec, API, authorization, CAS, quota, summary-query cost,
outbox, GC, importer retry, cancellation, corruption, and
cross-workspace tests pass. Request and worker cost is bounded by declared
file, byte, row, batch, and binding quotas rather than workspace history.

### Phase 2: migrate existing functionality

This phase has two delivery stages because server-owned domains and
Memory's local-first synchronization have different authority and
activation and failure boundaries.

#### Tree-consumer stage

Migrate Skill, Role, Knowledge Base, Knowledge QA, Automation, Activity, and
their Web/API callers to tree `ContentVersion` references. External Git becomes
a bounded server-side importer or mirror client. KB index and derived artifacts
remain KB-owned projections keyed by the exact input `ContentVersion`;
Automation run state replaces Git commit-status semantics.

The native Web surface exposes only product-required versions, files, compare,
and download. GitHub social features, clone/token UI, and other AGS product
surfaces selected for deletion are not recreated.

**Gate:** every active and retained tree reference opens through the Content
Store; active tree-domain paths contain no AGS HTTP/Git/token/collaborator/event
call; external import, outbox, projection rebuild, conflict, and retry tests
pass. AGS may remain only for unmigrated bindings and temporary read-only audit
or manual-recovery evidence.

#### Memory and Desktop stage

Desktop or the agent remains the live Memory owner. A local edit atomically
updates the working set, local version journal, and sync outbox before success.
The bounded worker coalesces unsynced versions into cloud checkpoints, retains
local state under network/quota/CAS/generation failure, and acknowledges the
covered local sequence range only after a durable tree `ContentVersion`
exists.

The initial release permits one active sync device per binding. Divergent
lineage preserves both local and remote content for explicit resolution. Restore
materializes a cloud checkpoint and creates a new local version; it never
silently rewinds the working set.

**Gate:** migrated Memory/Desktop paths have no AGS remote, credential, clone,
fetch, or push dependency. Offline edits, checkpoint coalescing, quota
backpressure, concurrent head, stale generation, duplicate delivery, crash
recovery, restore, and access revocation tests pass. All active product writers
now use the Content Store.

#### Common migration and cutover procedure

Backfill is an explicit admin operation, never server-startup or request-path
work. Each migrated domain follows the same bounded sequence:

1. inventory ownership, active references, retained history, backup labels,
   citations, Automation pins, Memory quota, and client versions;
2. implement the native reader, writer, authorization, event, and client path;
3. use existing AGS read interfaces, or the smallest migration-only bounded
   read/export seam when no existing interface can expose the selected
   immutable revision, to import required history into verified tree
   manifests/blobs without changing product references;
4. create or verify the idempotent
   `ags_repository_id + ags_commit_sha -> ContentVersion` mapping, including
   model, digest, byte count, and source metadata;
5. run one best-effort bounded delta observation, verify the selected
   counts/digests and representative reads, and record the start of the
   legacy-write loss window;
6. enforce the exact binding's legacy mutation cutoff across every AGS ingress
   and credential, rejecting new Git Smart HTTP, REST, GraphQL, repository-token,
   and stale-client writes without waiting for already accepted work to drain;
7. only after the cutoff succeeds, update bounded product references and
   atomically select the native owner; a deployment may perform these actions in
   one ordered step, but it may not expose native authority before the cutoff;
8. remove the migrated domain's remaining AGS helpers and event bridges, reject
   silent fallback, and record the cutoff/activation evidence plus any
   observable late-write count.

Progress and retry state belongs to AgentTeam's product migration owner and is keyed
by source repository/commit. AGS is not extended with a new generic receipt,
snapshot pin, projection worker, GC rule, deterministic commit protocol, or
replay queue for this migration. Every import batch has cursor, file, byte,
row, and time bounds. Tree objects precede references; path/digest summaries
commit transactionally with the version. A selected Memory history that
exceeds its finite quota blocks in preflight until an operator-approved
allocation exists; it is never truncated.

Historical import preserves product-visible canonical content, ordering,
timestamps, digests, backup labels, and exact references. It does not preserve
AGS's internal branch topology, merge DAG, server-generated commit identity, or
unreferenced repository objects unless a product contract explicitly exposes
them.

#### Cross-phase integration gate

The storage foundation and both consumer-migration units must also be combined
into one reproducible integration build before AGS deletion starts. The build
manifest records the immutable source revision for each unit and their
dependency order. Resolving a conflict must not squash or rewrite the units in
a way that hides their independently reviewable diffs or activation boundaries.

The integration environment uses one initialized schema and one coordinated
fixture set to exercise the real API, authorization, store, payload backend,
outbox, and client boundaries. It must prove all of the following as one
continuous product path:

- create tree content, write a version, advance its head with expected-head
  CAS, and read the exact version through native Skill, Role, Knowledge Base,
  Knowledge QA, Automation, and Activity paths;
- rebuild a KB projection from the exact input `ContentVersion` and consume
  the corresponding idempotent outbox event;
- accept an offline Memory edit locally, recover its journal/outbox after a
  restart, coalesce it into a canonical tree checkpoint, then exercise
  bounded cloud history, compare, and restore through Desktop;
- preserve local Memory state and pending outbox work under quota pressure,
  stale generation, concurrent head, access revocation, and unavailable
  storage; no native error may select AGS as a fallback;
- complete bounded historical import, one best-effort delta observation, the
  exact-binding legacy mutation cutoff, one-way authority switch,
  loss-window reporting, and native backup/restore with the generated active
  AGS inventory at zero; after activation, stale Git Smart HTTP, REST, GraphQL,
  repository-token, and product-client writes to the binding must fail closed.

Passing narrower unit or migration-unit suites does not substitute for this
gate. The physical delivery units remain independently reviewable and
can be aborted before activation. Their AGS reversibility ends at the one-way
authority switch; the combined build is validation evidence, not a new
authority or a permanent compatibility layer.

### Phase 3: remove AGS

The **deletion stage** starts only after the active inventory is zero:

- stop constructing AGS and remove it from worker, readiness, shutdown, route,
  raw-file, GraphQL, and Git Smart HTTP ownership;
- delete AGS identity, token, collaborator, repository authorization, event
  bridges, DTOs, Web/Desktop clients, and retired product surfaces;
- remove AGS schema orchestration, `MESHX_AGS_*`, `agentteam_ags`, bare-repository
  runtime/deployment ownership, module requirement/replacement, and
  `x/agent-git-service`;
- update release and coordinated backup/restore contracts to AgentTeam Core, MeshX
  `ContentVersion` data, native tree payloads, and their explicit data
  roots.

AGS database and bare repositories remain read-only through a declared audit
and manual-recovery retention window. They are not an automatic write rollback
target. Destructive database or volume cleanup is a separate operator action
after retention expiry and native restore evidence; it is not part of the code
deletion stage.

**Gate:** generated inventories for AGS imports, callers, routes, protocols,
configuration, schema, module, runtime, deployment, clients, and active data
ownership are zero. Clean install, upgrade, native backup/restore, one-way
cutover, and post-cutover code rollback/forward-fix suites pass without using
AGS as a writer.

### Optional S3 backend

S3 is not required for AGS removal. If introduced, it implements the existing
`TreePayloadBackend` contract and test suite, including multipart interruption,
checksum mismatch, range reads, idempotent upload, bounded concurrency,
workspace isolation, retention/GC, and cost tests. Head ownership remains in
the MeshX database and request paths never use `ListObjects` as an index.

## Abort and post-cutover recovery boundaries

Before native writes begin, operators may abort the migration and keep AGS as
the owner. Imported ContentVersions and mappings remain dormant and may be
reused or garbage-collected by their normal native policies.

After native writes begin, authority does not return to AGS. A code rollback
must deploy a version that still reads and writes the Content Store, otherwise
the system is forward-fixed. The runbook must not reverse-export native
versions, dual-write to AGS, point old AGS code at native payload storage, or
combine current product references with an older AGS volume.

Read-only AGS retention can support manual investigation or a separately
approved one-off recovery. It does not change authority and does not promise
recovery of legacy writes inside the accepted deployment loss window.

## Verification and drift control

Current inventory can be regenerated with focused searches such as:

```bash
rg -l 'github\.com/pingcap/agent-git-service' --glob '!x/agent-git-service/**' --glob '*.go' .
rg -n '/api/v3|/api/graphql|/api/ext/v1|MESHX_AGS_|agentteam_ags|ags_rat_|agent-git-service' \
  internal cmd web desktop dev scripts specs go.mod Dockerfile* docker-compose*
```

These searches are discovery evidence, not the final guardrail: generated
inventories must classify intentional historical provenance separately from
active code, tests, configuration, and canonical documentation. Every stage
lowers the active baseline; no stage raises it to absorb new AGS coupling.

Required validation includes targeted Content Store/domain/Desktop tests, schema
init/verify on supported databases, route and boundary negative fixtures,
bounded importer retry and corruption tests, full-plus-best-effort-delta import,
loss-window reporting, one-way cutover, post-cutover no-fallback behavior,
`git diff --check`, and `make harness-fast`.
