# Phase 4 — Emit

Compose the TOML from Phase 1-3 variables, ensure a keypair exists, write
`~/.claude/pet/<user_id>.toml`, display a summary, suggest next steps.

## 4a — User ID (keygen if needed)

Check whether a keypair already exists:

```bash
kei-pet keygen --status 2>/dev/null
```

Expected outputs:

- `keypair exists, user_id=<short-hash>` → reuse; set `USER_ID` to the hash,
  set `KEYGEN_ACTION = "reused existing"`
- `no keypair` OR non-zero exit → create one:

```bash
kei-pet keygen --create
```

Capture the new `user_id` short-hash from stdout. Set `USER_ID` to that
hash, set `KEYGEN_ACTION = "newly created"`.

If `kei-pet keygen --create` fails (non-zero exit, no hash in stdout) →
STOP and emit 3 constructive paths:

- (A) check that the `kei-pet` binary is on `$PATH`; point user to
  `install.sh --profile=dev`
- (B) invoke the raw primitive at `_primitives/_rust/kei-pet/target/release/kei-pet keygen --create`
- (C) manually set `USER_ID = "anonymous"` for a one-off local pet; warn
  that this pet will not be portable across machines

Never silently fall through without a `USER_ID`.

## 4b — Compose TOML in memory

Build the TOML string exactly matching the schema in
`_primitives/_rust/kei-pet/examples/minimal.toml`. Use these variable
substitutions (all gathered in Phases 1-3 unless noted):

```toml
# Pet manifest for <PET_NAME> (owner <USER_NAME>, user_id <USER_ID>)
# Generated by /pet-init on <ISO8601-UTC-NOW>.

schema = 1

[identity]
pet_name    = "<PET_NAME>"
user_name   = "<USER_NAME>"
addressing  = "<ADDRESSING>"
languages   = [<comma-separated-quoted-LANGUAGES>]

[voice]
tone_primary    = "<TONE_PRIMARY>"
tone_secondary  = [<comma-separated-quoted-TONE_SECONDARY>]
humor_style     = "<HUMOR_STYLE>"
humor_frequency = "<HUMOR_FREQUENCY>"

[edge]
profanity            = "<PROFANITY>"
profanity_languages  = []
directness           = "<DIRECTNESS>"
initiative           = "<INITIATIVE>"

[forbidden]
topics        = [<comma-separated-quoted-FORBIDDEN_TOPICS>]
tone_patterns = []

[meta]
schema_version_written_by = "kei-pet 0.1.0"
created_at                = "<ISO8601-UTC-NOW>"
last_tuned                = "<ISO8601-UTC-NOW>"
tune_count                = 0
```

String escaping rules inside double-quoted TOML values:

- escape `\` → `\\`
- escape `"` → `\"`
- reject control chars other than TAB (should never appear; guard)

Timestamps: emit current UTC time in RFC 3339 with `Z` suffix, e.g.
`2026-04-23T12:30:00Z`. `created_at` and `last_tuned` are equal on first
init.

## 4c — Write the file

Target path: `~/.claude/pet/<USER_ID>.toml` (absolute: expand `~` to `$HOME`).

```bash
mkdir -p "$HOME/.claude/pet"
```

Then write the composed TOML to `$HOME/.claude/pet/<USER_ID>.toml`. Use
the `Write` tool with the absolute path — do NOT echo TOML through shell
(quoting hazard).

If the file already exists at that path (re-run of `/pet-init` for the
same user_id), rename the existing file to
`~/.claude/pet/<USER_ID>.toml.bak-<ISO8601-UTC-NOW>` BEFORE writing the
new one. Tell the user: `Previous pet.toml backed up to <bak-path>`.

## 4d — Validate (best-effort)

Attempt a schema validation via the primitive:

```bash
kei-pet validate --pet "$HOME/.claude/pet/<USER_ID>.toml"
```

- exit 0 → good; proceed
- non-zero → emit the validator's stderr verbatim, keep the file on disk
  (the user can re-run `/pet-init` to fix), set `VALIDATION = "FAILED"`
- command not found → set `VALIDATION = "SKIPPED (kei-pet not on PATH)"`

## 4e — Summary table + next steps

Emit a plain-text summary (NOT AskUserQuestion — this is the closing
message):

```
=== PET-INIT REPORT ===
Pet name:        <PET_NAME>
Addressed by:    <USER_NAME> via <ADDRESSING>
Languages:       <LANGUAGES joined with comma-space>
Voice:           <TONE_PRIMARY> (+ <TONE_SECONDARY or "no secondary">)
Humor:           <HUMOR_STYLE> @ <HUMOR_FREQUENCY>
Edge:            <DIRECTNESS> / <INITIATIVE> / profanity=<PROFANITY>
Forbidden:       <FORBIDDEN_TOPICS joined with comma-space, or "(none)">
File:            ~/.claude/pet/<USER_ID>.toml
Keygen:          <KEYGEN_ACTION>
Validation:      <PASSED | FAILED | SKIPPED>

Next:
  /pet-chat
  kei-pet render --pet ~/.claude/pet/<USER_ID>.toml
```

## Verify-criterion

- `USER_ID` is a non-empty short-hash OR the documented `"anonymous"`
  fallback (only via constructive path C in 4a)
- `~/.claude/pet/<USER_ID>.toml` exists on disk and matches the composed
  TOML byte-for-byte
- If a prior file existed, a `.bak-<ts>` backup exists alongside it
- Summary table is emitted with all 10 rows filled (no placeholders left)
- `kei-pet validate` was attempted; its verdict is surfaced

## Failure modes (constructive paths)

If `Write` fails (permission denied, read-only filesystem, disk full):
- (A) fall back to `~/Desktop/<USER_ID>.toml` and tell the user to move
  the file manually
- (B) print the full TOML to stdout so the user can paste it anywhere
- (C) invite the user to re-run `/pet-init` after fixing the underlying
  disk/permission issue

If `kei-pet validate` reports a schema violation that the wizard could
not anticipate (schema drift between this skill and the binary):
- (A) keep the file; tell the user the specific validator error
- (B) suggest `kei-pet migrate --pet <path>` if the primitive ships one
- (C) open an issue link to the KeiSeiKit repo for schema-drift reports

Never silently succeed while validation is failing.
