Personalized variants (default trigger: salva.md) compile to a separate
top-level folder so generated/<persona>/ stays clean of per-user content.
Both the trigger variant filename(s) and the output folder name are
config-driven via config.user — the build is truly user-agnostic.
Build changes:
- Module-level _RUNTIME dict cached by configure_runtime(config) at startup
- resolve_personalized_variants(config) — config.user.personalized_variants
- resolve_personalized_output_dirname(config) — slug-derives from
user.name (e.g. "Salva" → "salva-personas") with explicit override key
- resolve_personalized_source_dirname(config) — defaults to literal
"personalized" (gitignorable, user-name-independent)
- iter_persona_output_dirs() — single helper used by all install_*()
functions to transparently iterate both layouts
- build_persona() routes salva variants based on _RUNTIME at write time
- build_skills_index() also scans <repo>/personalized/skills/ so personal
skills (with user-private data) merge into the shared skill index
- main() picks up persona dirs from BOTH personas/ and personalized/
New config keys (all optional):
- user.personalized_variants
- user.personalized_output_folder
- user.personalized_source_folder
Output layout (e.g. for user.name="Salva"):
- generated/<persona>/general.{json,yaml,prompt.md} (shared)
- generated/<persona>/<spec>.{json,yaml,prompt.md} (shared)
- generated/salva-personas/<persona>/salva.{json,yaml,prompt.md} (private)
Source layout:
- personas/<persona>/general.md, <spec>.md (committed)
- personalized/<persona>/salva.md (gitignored)
- personalized/skills/<skill>/SKILL.md (gitignored)
- personalized/_user_context.md (gitignored)
Adds /personalized/ to .gitignore. Documents the new layout in CLAUDE.md
and README.md. Maps linkedin-content-strategy → herald/forge/frodo/ghost
in the default skill persona map.