> ## Documentation Index
> Fetch the complete documentation index at: https://prism.ntecdev.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SPEC-090 v0.1: prism_adopt — explicit existing-repository project adoption

> SPEC-090 v0.1 — Add prism_adopt as the safe, explicit verb for registering an already-local git worktree as a Prism project without cloning, moving, or modifying application code.

<Info>**Status:** `draft` · **Version** `0.1` · Filed 2026-05-07</Info>

***

version: 0.1
status: draft
-------------

# SPEC-090 v0.1 — `prism_adopt`: explicit existing-repository project adoption

## Origin

Frank is onboarding existing DFW/Keyz work on Windows mini1. The immediate case is an existing local repo for `Keyz4me/Keyz`, with related repos/components such as `KaiBot` and `CFD`.

Today the closest working verb is `prism_clone`. Its implementation already has a hidden `register` mode: if `project_dir` exists and contains `.git`, it skips `git clone` and calls backend bootstrap with `strategy="register"`. That works mechanically, but the operator language is wrong. "Clone this repo" and "adopt this repo" are different intents:

* **Clone** means the repo is not local yet. Prism performs a checkout.
* **Adopt** means the repo already exists locally. Prism binds it into Prism state.

The difference matters because adopting an existing worktree must never clone over, move, reinitialize, or rewrite the application code. The operator should be able to say "adopt this repo" and get a safe register-only path.

## §1 — Goals

1. Add an explicit `prism_adopt` MCP verb for existing local git repositories.
2. Keep `prism_clone` focused on clone/check-out semantics.
3. Make adoption safe by construction: no `git clone`, no `git init`, no code movement, no application-code edits.
4. Support Windows editor-host onboarding from Cursor/Claude Code/Codex on mini1.
5. Preserve the existing backend bootstrap behavior by using `strategy="register"`.
6. Make multi-repo onboarding clear: one Prism project/PID per repo. The GitHub owner/org is repository metadata; it is not the same thing as a Prism org/tenant.

## §2 — Non-Goals

* No monorepo component model in v0.1. If `KaiBot` and `CFD` are folders inside the `Keyz` repo, they are tracked as components/spec areas inside the `Keyz` Prism project. If they are separate repos, each gets its own Prism project.
* No automatic mutation during plain `prism_start`. `prism_start` may detect an untracked repo and recommend adoption, but adoption remains an explicit verb call.
* No source-code scaffolding or framework migration. This verb only binds Prism metadata and BIOS/methodology files.
* No repo creation on GitHub. If the remote does not exist, fail with a clear preflight error.

## §3 — Verb Contract

```ts theme={null}
prism_adopt(
  name: string,
  project_dir: string,
  github_repo?: string,
  repo_owner?: string,
  prism_org?: string,
  ptype?: string = "application",
  persona?: string = "Bot",
  force?: boolean = false
)
```

### Required fields

* `name` — Prism project display/name slug, e.g. `Keyz`.
* `project_dir` — absolute or workspace-resolved path to the existing local repo.

### Optional fields

* `github_repo` — canonical repo owner/name or URL, e.g. `Keyz4me/Keyz`.
* `repo_owner` — GitHub owner/org hint, e.g. `Keyz4me`. This is derived from `github_repo` when omitted.
* `prism_org` — future Prism org grouping hint. In v0.1 this is normally omitted; adoption lands under the current Prism tenant/personal install unless backend project→org binding has shipped.
* `ptype` — project type, default `application`.
* `persona` — initial/default persona, default `Bot`.
* `force` — bypass only narrowly defined metadata mismatch guards; never bypasses destructive-code protections.

## §4 — Required Preflight

`prism_adopt` MUST fail before backend mutation unless all required checks pass:

1. `project_dir` exists.
2. `project_dir/.git` exists.
3. `project_dir` is not the Prism repo itself unless `name` resolves to Prism.
4. `git rev-parse --show-toplevel` succeeds and equals/resolves to `project_dir`, or returns a clear nested-worktree warning. On Windows this comparison MUST canonicalize separators and drive-letter case before comparing.
5. If `github_repo` is provided, `git remote get-url origin` must match it after normalization, or adoption must stop unless `force=true`.
6. If `github_repo` is omitted, try to derive it from `origin`; if derivation fails, return a structured preflight error asking for `github_repo`.
7. If `repo_owner` is omitted and `github_repo` has an owner, derive `repo_owner` from the repo owner. Do not treat the GitHub owner as a Prism org.
8. If `prism_org` is provided, preserve it as a future Prism grouping hint only. First-class Prism org enforcement waits for the project→org binding model.
9. Existing Prism project conflicts are handled explicitly:
   * Same `project_dir` already bound: return existing PID, idempotent success.
   * Same `github_repo` already bound to different path: fail with conflict unless `force=true` and backend supports a safe rebind.
   * Same `name` already bound to a different repo in the current Prism tenant/personal install: fail with conflict.

## §5 — Behavior

On successful preflight:

1. Call backend project bootstrap with:

```json theme={null}
{
  "name": "<name>",
  "projectDir": "<project_dir>",
  "strategy": "register",
  "persona": "<persona>",
  "ptype": "<ptype>",
  "githubRepo": "<normalized github_repo>"
}
```

2. Load project context by returned PID.
3. Sync Prism BIOS/methodology files with `syncBios({ files: "all", force: false })`.
4. Write no application files except Prism-owned project metadata/docs:
   * `PRISM.md`
   * `AGENTS.md`
   * `CLAUDE.md`
   * no local `.prism/project.json` binding file in v0.1; backend remains the source of truth
5. Return a structured result:

```json theme={null}
{
  "pid": "PID-...",
  "project_dir": "...",
  "mode": "adopt",
  "github_repo": "Keyz4me/Keyz",
  "repo_owner": "Keyz4me",
  "prism_scope": "personal",
  "origin_url": "...",
  "bootstrap_result": {},
  "sync_result": {},
  "next": {
    "start": "prism_start(name=\"Keyz\", identity=\"Cherry\")"
  }
}
```

## §6 — Relationship To `prism_clone`

Current `prism_clone` behavior:

| Local state                             | Current behavior                     |
| --------------------------------------- | ------------------------------------ |
| Directory missing/empty + repo supplied | Clone repo, then bootstrap           |
| Directory exists with `.git`            | Register existing repo without clone |

SPEC-090 changes operator semantics:

| Verb          | Intent                                    | Allowed to clone? | Requires `.git` already present? |
| ------------- | ----------------------------------------- | ----------------: | -------------------------------: |
| `prism_clone` | Remote repo checkout into a local project |               Yes |                               No |
| `prism_adopt` | Bind existing local worktree into Prism   |                No |                              Yes |

Implementation may initially share helper code with `prism_clone`, but the public verb contracts stay separate.

`prism_clone` keeps its current existing-repo register fallback for a deprecation window. When that fallback is used after `prism_adopt` ships, it SHOULD return a warning:

> Existing local git repo detected. `prism_adopt` is the preferred verb for registering existing repos; `prism_clone` register fallback is retained for compatibility and may be removed in a later v0.2 change.

## §7 — Windows / mini1 UX

For an existing repo:

```text theme={null}
prism_adopt(
  name="Keyz",
  github_repo="Keyz4me/Keyz",
  repo_owner="Keyz4me",
  project_dir="C:\\DATA\\Keyz",
  ptype="application",
  persona="Cherry"
)
```

`persona` should refer to an existing persona when possible. For a new operator persona such as `Cherry`, run `prism_persona_create` first unless the active backend explicitly supports lazy persona creation during `prism_start` / controller registration.

For three separate repos under a common workspace root:

```text theme={null}
prism_adopt(name="Keyz",   github_repo="Keyz4me/Keyz",   project_dir="C:\\DATA\\DFW\\Keyz")
prism_adopt(name="KaiBot", github_repo="Keyz4me/KaiBot", project_dir="C:\\DATA\\DFW\\KaiBot")
prism_adopt(name="CFD",    github_repo="Keyz4me/CFD",    project_dir="C:\\DATA\\DFW\\CFD")
```

For one repo with components:

```text theme={null}
C:\DATA\DFW\Keyz\
  .git\
  KaiBot\
  CFD\
```

Adopt only `Keyz`; track `KaiBot` and `CFD` as components/spec areas inside the `Keyz` project.

## §8 — `prism_start` Integration

`prism_start` must not silently adopt. It MAY detect the untracked-repo case and return a reminder:

> This git repository is not registered as a Prism project. To bind it without cloning or moving files, run `prism_adopt(name=..., project_dir=...)`.

Detection should be advisory only in v0.1.

## §9 — Implementation Notes

Likely first implementation is a small refactor in `mcp-node/src/verbs/tier1c.ts`:

1. Extract shared helper from `prism_clone` register path:
   * resolve project dir
   * inspect git remote
   * canonicalize paths cross-platform before comparing `project_dir` and `git rev-parse --show-toplevel`
   * call `client.bootstrapProjectApi({ strategy: "register" })`
   * load context and run `syncBios`
2. Add `registerVerb({ name: "prism_adopt", ... })`.
3. Add tests for:
   * existing git repo adopts successfully
   * missing dir fails
   * non-git dir fails
   * remote mismatch fails
   * existing binding is idempotent
   * Windows path comparison handles `C:\Foo\Bar` vs `c:/Foo/Bar`
   * no `git clone` command is invoked

Backend/router gap to close before or during implementation: same-path adoption must be idempotent. Before INSERT, the backend bootstrap path should check for an existing project row for `(tenant_id, project_dir)` and return the existing PID rather than creating a duplicate.

## §10 — Acceptance Criteria

1. On Windows mini1, Cherry can adopt an existing `Keyz4me/Keyz` checkout from Cursor without cloning.
2. The adopted project appears in `prism_status` / `prism_start` with a PID.
3. The project receives Prism BIOS files.
4. Re-running `prism_adopt` on the same path returns the same PID and does not duplicate project records.
5. A mismatched `origin` vs `github_repo` returns a structured conflict.
6. Existing `prism_clone` behavior is not broken.

## §11 — Open Questions

1. Should `repo_owner` be stored explicitly or derived from normalized `github_repo` everywhere?
2. Should `prism_clone` keep its current register fallback for backward compatibility, or should it start warning that existing repos should use `prism_adopt`?
3. When project→Prism-org binding ships, should `prism_org` become required for hosted/customer-mode adoption?

## §12 — Related

* `mcp-node/src/verbs/tier1c.ts` — current `prism_create` / `prism_clone` implementation.
* SPEC-054 — Node MCP shim / install migration context.
* SPEC-055 — target registry and operator lifecycle verbs.
* SPEC-056 — multi-tenant routing / org identity model.
* SPEC-087 / SPEC-089 — cloud org/auth context for customer onboarding.
