Commit graph

11 commits

Author SHA1 Message Date
pyr0ball
457276e302 feat: language mascot system + script-first architecture (v0.2.0)
Language mascots:
- 11 mascots across common/uncommon/rare/legendary tiers (Pythia, Asynclet,
  Bashling, Goroutling, Typeling, Vueling, Querion, Ferrix, Perlius,
  Cobolithon, Lispling)
- Full evolution chains for all mascots (16 evolutions total in catalog)
- Spawn via PostToolUse after language affinity milestones; probability
  scales with affinity level; only fires with no active encounter
- Passive strength reduction: each Write/Edit in the mascot's language
  ticks current_strength down (floor 5%, triggers re-announcement)
- Mascot-aware catch formula: base_rate + affinity_bonus (6% per level) +
  weakness_bonus + soft element gating via existing player_elements
- Language-themed weakening menu and catch failure messages in CLI
- Caught mascots stored as type="caught_language_mascot"; assignable as buddy
- UserPromptSubmit uses distinct 🦎 announcement with language context

Roster display:
- New "Language Mascots" section between core buddymon and caught bug monsters
- Language affinity table marks languages with spawnable mascots (🦎)
- Discovery counter now tracks both bug monsters and mascots separately

Veritarch (third evolution):
- Debuglin → Verifex (Lv.100) → Veritarch (Lv.200)
- TYPE FORTRESS / INVARIANT PROOF / ZERO FLAKE challenges
- xp_multiplier 1.7, catch_rate 0.90

Script-first architecture:
- All game logic extracted to lib/cli.py (~850 lines); SKILL.md is now
  a ~55-line relay — 88% token reduction per invocation
- CLI emits [INPUT_NEEDED] and [HAIKU_NEEDED] markers for interactive flows
- PostToolUse hook re-emits CLI stdout as additionalContext for inline display

Session XP fix:
- statusline.sh and session state now read from sessions/<pgrp>.json
  (per-window) with fallback to active.json; fixes stale XP in statusline
2026-04-10 01:31:51 -07:00
pyr0ball
c12a234652 fix: catch_pending race condition — hook clears flag, not the roll script
Previously the catch roll script wrote catch_pending=False to disk before
the Bash process exited. The PostToolUse hook fired after exit, saw False,
and could auto-resolve the encounter on the same run as the catch attempt.

Fix: the hook now owns the flag lifecycle.
- Hook clears catch_pending after consuming it (protects exactly one run)
- Roll script never touches catch_pending (no premature clear)
- On failure, flag stays True through the roll, cleared by hook afterward
- Next /buddymon catch call re-sets it at the top as before

Net effect: a failed catch attempt always gets one full clean Bash run of
grace before auto-resolve can fire again.
2026-04-05 23:58:08 -07:00
pyr0ball
910da843fe fix: robust catalog path resolution when CLAUDE_PLUGIN_ROOT unset
Skills run via Bash heredoc don't inherit CLAUDE_PLUGIN_ROOT, so
f"{PLUGIN_ROOT}/lib/catalog.json" collapsed to /lib/catalog.json.

All four PLUGIN_ROOT usages in SKILL.md now try:
  1. $CLAUDE_PLUGIN_ROOT/lib/catalog.json  (if env var is set)
  2. ~/.claude/plugins/marketplaces/circuitforge/plugins/buddymon/lib/catalog.json
  3. ~/.claude/plugins/cache/circuitforge/buddymon/0.1.1/lib/catalog.json

statusline block also fixed: prefers ~/.claude/buddymon/statusline.sh
(stable user-local copy from install.sh) over plugin-relative paths.
2026-04-05 23:40:57 -07:00
pyr0ball
1ed888db72 fix: skill catch — auto-throw at 5%, session file fallback to active.json
- wounded encounters (5% strength) skip weakening Q&A and go straight
  to the throw — no more 'want to throw?' prompt at 5%
- catch roll now tries sessions/<pgrp>.json first, falls back to
  active.json if missing (fixes FileNotFoundError in new windows that
  haven't run any tools yet)
- XP write follows the same fallback pattern
2026-04-05 23:32:03 -07:00
pyr0ball
c85bade62f feat: per-session buddy isolation via PGRP-keyed state files
Each Claude Code session now gets its own state file at:
  ~/.claude/buddymon/sessions/<pgrp>.json

Contains: buddymon_id, session_xp, challenge — all session-local.
Global active.json keeps the default buddymon_id for new sessions.

/buddymon assign writes to the session file only, so assigning in one
terminal window doesn't affect other open sessions. Each window can
have its own buddy assigned independently.

SessionStart creates the session file (inheriting global default).
SessionStop reads XP from it, writes to roster, then removes it.
2026-04-02 23:11:19 -07:00
pyr0ball
8e0a5f82cb feat: evolution system — prestige to evolved form at Lv.100
Evolution triggers at Lv.100 for all three starters:
  Pyrobyte → 🌋 Infernus  (power 40→70, catch_rate 0.45→0.55)
  Debuglin → 🔬 Verifex   (power 35→60, catch_rate 0.60→0.75)
  Minimox  → 🌑 Nullex    (power 35→55, catch_rate 0.50→0.65)

/buddymon evolve: checks eligibility, shows stat preview, resets buddy
to Lv.1 in evolved form, archives old form with evolved_into marker,
carries challenges forward.

session-stop.sh now prints EVOLUTION READY banner when level hits 100
or when already eligible at session end.
2026-04-02 23:08:32 -07:00
pyr0ball
85f53b1e83 feat: catch-pending flag + wounded state for encounter resolution
catch_pending: set immediately when /buddymon catch is invoked, suppresses
auto-resolve while weakening Q&A is in progress. Cleared before catch roll
(success clears encounter, failure leaves it without the flag so auto-resolve
resumes naturally on the next clean Bash run).

wounded: first clean Bash run without catch_pending drops the encounter to 5%
strength and re-announces via UserPromptSubmit with a fleeing message. Second
clean run auto-resolves it (it fled). UserPromptSubmit now shows distinct
announcement text for wounded vs fresh encounters.
2026-04-02 22:37:35 -07:00
pyr0ball
0c311b099b feat: buddymon statusline widget
Adds lib/statusline.sh — a fast bash+jq status bar widget showing
active buddy, level, session XP, and any active encounter in red.

install.sh now copies the script to ~/.claude/buddymon/statusline.sh
and wires it into settings.json automatically during install.

/buddymon statusline subcommand documented in SKILL.md for manual install.
2026-04-02 22:31:37 -07:00
pyr0ball
a9c5610914 feat: language affinity system — persistent XP + tier progression
Adds LANGUAGE_TIERS with 6 tiers: discovering → familiar → comfortable
→ proficient → expert → master (thresholds: 0/50/150/350/700/1200 XP).

add_language_affinity() writes to roster.json['language_affinities'],
accumulating across sessions. Returns (leveled_up, old_tier, new_tier)
so the Edit/Write branch can fire a level-up message immediately (Edit
PostToolUse additionalContext surfaces fine).

Session-level languages_seen remains for the one-time Explorer bonus.
Roster skill view updated to show language affinity section.
2026-04-02 22:23:31 -07:00
pyr0ball
46734e79c8 feat: auto-resolve encounters on clean Bash runs
When an active encounter exists and the next Bash tool call produces
output with no matching error patterns, the monster is automatically
defeated and XP is awarded — no manual /buddymon fight needed.

/buddymon fight is kept as a manual fallback for fixes that happen
outside Bash (config edits, etc.).
2026-04-01 15:15:02 -07:00
pyr0ball
f3d1f45253 feat: initial Buddymon plugin
Claude Code plugin — collectible creatures discovered through coding.

- Bug monsters spawn from error output (NullWraith, RacePhantom, ShadowBit, 11 total)
- 5 Buddymon with affinities, challenges, and evolution chains
- SessionStart hook injects active buddy + challenge into system context
- PostToolUse hook detects error patterns, new languages, and commit events
- Stop hook tallies XP and checks challenge completion
- Single /buddymon command with start/assign/fight/catch/roster subcommands
- Local state in ~/.claude/buddymon/ (roster, encounters, active, session)
2026-04-01 15:11:46 -07:00