KeiSeiKit-1.0/skills/pet-init/phase-4-emit.md
Parfii-bot a4e667de10 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

5.3 KiB

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:

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:
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):

# 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).

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:

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.