# 1.11.0 — `init-meta`: generate a missing draft_meta_info.json

Minor release. One new command, zero changes to existing behavior. It is the last
of the validate→fixer family: where v1.8.0 `validate` *reports* `meta.missing`,
`init-meta` *generates* the missing sidecar.

## The problem it solves

A draft directory needs a `draft_meta_info.json` next to its `draft_content.json`
for CapCut to **list** it and for `register` to index it. Drafts generated outside
`psycho-build` (hand-assembled, copied, scripted) can lack it — they're then
invisible in the CapCut UI, and `register` fails. `validate` flags this as
`meta.missing`; `init-meta` fixes it.

## Highlights

- 🩹 **`capcut-david init-meta <project>`** — writes the canonical
  `draft_meta_info.json` (the same ~40-field shape `psycho-build` emits) next to a
  draft's `draft_content.json` when it's missing.
- 🛡️ **Refuse-to-clobber — the INVERSE posture of `sync-timelines`/`gc`.** An
  *existing* sidecar is presumed authoritative (it holds the real `draft_id`,
  timestamps, cloud refs), and `meta.missing` only fires when the file is **absent**
  — so `init-meta` **refuses** to overwrite one (exit 1, zero bytes) unless `--force`
  (which backs up the original to `.bak` first).
- 🎯 **Writes only the meta sidecar.** Never `draft_info.json`, never
  `root_meta_info.json` (except the opt-in `--register`), never `draft_content.json`.
- 🧬 **Identity from disk** (matches `register`): `draft_id` from the content (or a
  fresh UUID), `draft_name` = dir basename, `draft_root_path` = the parent dir,
  `tm_*` in microseconds.
- ♻️ **Shared builder.** `buildDraftMetaInfo` was extracted verbatim from
  `psycho-build` into `src/utils/draft-meta.ts` so both emit a byte-identical
  sidecar (locked by an exact key-order test).
- ✅ **375 tests** (+13). `init-meta.js` 97.8% lines / 100% functions. Typecheck + lint clean.

## Usage

```
$ capcut-david init-meta my-draft              # create the sidecar (refuses if present)
$ capcut-david init-meta my-draft --dry-run    # report what WOULD be written, write nothing
$ capcut-david init-meta my-draft --force      # overwrite an existing sidecar (.bak first)
$ capcut-david init-meta my-draft --register   # also index it in CapCut (chains register)
```

The full meta→register chain (each step `validate` can verify):

```
$ capcut-david validate my-draft         # error: meta.missing (no draft_meta_info.json)
$ capcut-david init-meta my-draft        # create the sidecar
$ capcut-david validate my-draft         # warning: meta.unregistered
$ capcut-david register my-draft         # index it → appears in CapCut
# (or `init-meta my-draft --register` to do the last two at once)
```

JSON envelope (`capcut-david/init-meta@1`):

```json
{
  "schema": "capcut-david/init-meta@1",
  "ok": true,
  "dry_run": false,
  "project": "C:\\...\\My Draft",
  "draft_file": "C:\\...\\My Draft\\draft_content.json",
  "meta_path": "C:\\...\\My Draft\\draft_meta_info.json",
  "draft_id": "…",
  "draft_name": "My Draft",
  "wrote": true,
  "registered": false,
  "root_meta_path": null
}
```

**Exit codes:** `0` = created (or dry-run / register OK), `1` = tool failure
(draft not found, the resolved file isn't `draft_content.json`, a sidecar already
exists without `--force`, or a write/register failure). No exit 2.

## Migration

**None.** `init-meta` is additive; no existing command changes output. The
`buildDraftMetaInfo` extraction is byte-identical, so `psycho-build` is unaffected.

## Compatibility

- CapCut ≥ 5.x desktop (Windows + macOS), JianYing 6+ unsupported — unchanged.
- Node `>= 18` — unchanged.
- Runtime dependencies: zero — unchanged.

## Roadmap (1.x — non-binding)

With the fixer family complete (`sync-timelines`, `gc`, `init-meta` + `register`),
the natural next step is a **`validate --fix`** umbrella that maps each finding id
to its fixer. Remaining backlog: `capcut-david query` (catalogue lookup); the
restyle "System" font-dropdown cosmetic quirk.
