# Phase 4 — Emit Compose the TOML from Phase 1-3 variables, ensure a keypair exists, write `~/.claude/pet/.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=` → 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 (owner , user_id ) # Generated by /pet-init on . schema = 1 [identity] pet_name = "" user_name = "" addressing = "" languages = [] [voice] tone_primary = "" tone_secondary = [] humor_style = "" humor_frequency = "" [edge] profanity = "" profanity_languages = [] directness = "" initiative = "" [forbidden] topics = [] tone_patterns = [] [meta] schema_version_written_by = "kei-pet 0.1.0" created_at = "" last_tuned = "" 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/.toml` (absolute: expand `~` to `$HOME`). ```bash mkdir -p "$HOME/.claude/pet" ``` Then write the composed TOML to `$HOME/.claude/pet/.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/.toml.bak-` BEFORE writing the new one. Tell the user: `Previous pet.toml backed up to `. ## 4d — Validate (best-effort) Attempt a schema validation via the primitive: ```bash kei-pet validate --pet "$HOME/.claude/pet/.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: Addressed by: via Languages: Voice: (+ ) Humor: @ Edge: / / profanity= Forbidden: File: ~/.claude/pet/.toml Keygen: Validation: Next: /pet-chat kei-pet render --pet ~/.claude/pet/.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/.toml` exists on disk and matches the composed TOML byte-for-byte - If a prior file existed, a `.bak-` 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/.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 ` 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.