id: fragment.editor-save-for-reuse.001
freshvibe_way_version: v8
date: 2026-07-31
last_rewritten: 2026-07-31 (Phase 8 v2 — content-types move from VibeCoder bridge)

# editor-save-for-reuse — review and keep the content types VibeCoder invents

## What it does

When VibeCoder (or any LLM working in the chrome) invents a new content type while building an app (e.g. a recipe's ingredients, a property's price), the type is created as a **draft** in the per-site content store. The operator opens this panel to review the drafts and decide which ones to keep for future reuse.

**Saved types** (status: `active`) are made available to the intent-to-type mapping in `runtime/content-types/intent-mapping.js`. The next time a similar app is built, the LLM gets the saved types as part of its context and can reuse them instead of re-inventing.

## Why this is its own feature

This is the **per-kind why-save message** (b243 Rule 4) + **shared-field detection** (b243 Rule 3) + **status lifecycle** (b243 Rule 1) + **site-scope default** (Phase 8 v2 Rule 8) — all in one operator-facing panel. Cluster rule holds:

1. **List drafts** — show every content type with status=draft, plus every saved type (status=active)
2. **Show the operator the "why save" sentence** — per-kind: "So the next recipe / food app reuses these fields instead of re-deriving them."
3. **Show the operator the shared-field breakdown** — "5 of 8 fields you already have on other content types. 3 are brand new."
4. **Show the operator the "what this is for" sentence** — from the type's `description` field
5. **One-click promote to active** — PATCH status from `draft` to `active`
6. **One-click dismiss** — PATCH status to `archived` (soft-delete, history preserved)
7. **Site-scope default** — saved types default to this site only. Operator can opt-in to "share globally" via a toggle.

## The 6 save-for-reuse rules (per b243)

| Rule | Source | What the operator sees |
|---|---|---|
| **1. Status lifecycle** | `runtime/content-types/cache.js` | Drafts → Active (kept) or Archived (dismissed). No hard delete. |
| **2. `origin_intent` + `origin_app` audit trail** | `runtime/content-types/cache.js` | Every saved type remembers what the user said + which app first used it. |
| **3. Shared-field detection** | `runtime/content-types/field-comparison.js` | "5 of 8 fields you already have. 3 are brand new." |
| **4. Per-kind why-save message** | `runtime/content-types/descriptors.js` | "So the next recipe / food app reuses these fields..." |
| **5. Intent-to-type mapping** | `runtime/content-types/intent-mapping.js` | 5 categories (BlogPost, Listing, Product, Recipe, Event), 4-7 keywords each. |
| **6. 5-min cache** | `runtime/content-types/cache.js` | Type changes take up to 5 min to propagate. Manual "Refresh cache" button. |

Plus the 2 new rules from Phase 8 v2:
- **7. Lives in the chrome** — opened via the `{ }` Dev button, not a separate URL
- **8. Site-scoped default** — saved types are site-scoped, opt-in to global via "Share globally" toggle

## Usage

The editor-shell (or any chrome component) imports the panel:

```js
import { openSaveForReusePanel } from '../editor-save-for-reuse/index.js';

// Open the panel
const panel = openSaveForReusePanel({
  onClose: () => { /* close the dock chip */ }
});
```

The panel is a self-contained DOM element. It appends itself to the body, manages its own state, and removes itself on close.

## Where the data comes from

Per Phase 8 v2: the panel reads from the **per-site content store** (via `runtime/content-types/cache.js`). No bridge calls. No VPS dependency. The store is site-scoped by default, with `scope: 'site'` on every saved type. The operator can toggle a type to `scope: 'global'` to share it across sites.

## How it relates to other features

- **editor-content-admin** — uses the same content store, but for the records (the data), not the types
- **editor-templates** — uses the same content store to build template proposals
- **inline-editor** — the operator's `{ }` button toggles the editor chrome; this panel is one of the panels that the chrome can open

## Contract

This fragment exposes exactly:
- `openSaveForReusePanel(opts)` → DOM element
- `closeSaveForReusePanel()` → void

Cross-module imports go through `index.js`, not `runtime/`. Implementation is in `runtime/content-types/`.
