feat: two-channel XP events, boosted rewards, world blessing, streak flames#144
Open
terpjwu1 wants to merge 10 commits into
Open
feat: two-channel XP events, boosted rewards, world blessing, streak flames#144terpjwu1 wants to merge 10 commits into
terpjwu1 wants to merge 10 commits into
Conversation
…flames commit/bug_fix/deploy XP rewards existed since the table was written but NOTHING ever fired them — every action was flat 5 XP and level 50 (104,925 XP) needed ~21,000 observes. Two detection channels fix that: - Ground truth: the PostToolUse hook sees the literal command + output + exit code; git commit / npm publish / wrangler deploy / passing test runs queue events in ~/.buddy/pending-events.jsonl (hooks stay free of native deps), ingested and awarded on the next buddy_observe - Self-report: classifySummary() keyword-matches the observe summary for events with no command signature (bug_fix) and hosts without hooks; the hook wins on duplicates within a window Rewards rebalanced (observe 8, session 5, tests_passed 20, commit 25, bug_fix 35, deploy 60) — an active day is ~700 XP instead of ~150, and level 50 is months, not years. The curve is deliberately untouched: world validation pins level === levelFromXp(xp) across client versions. Buddy World integration: - +10% XP blessing for teleported buddies (cached local check) - deploy/level_up/streak_7 bypass the sync debounce → plaza celebrations land within one poll of the real moment - streak milestones (every 7 days) emit streak_7; the plaza shows a 🔥 by the name for a week; tests_passed gets its own celebration + label - anti-abuse recalibrated for the new economy (900/hr cap, 300 burst) 33 new tests across classification, hook recording, pending-events handoff, blessing, streaks, and reward table. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verified against the official hooks reference (code.claude.com/docs/en/
hooks.md): tool_response is an object — {type:'text', text} on success,
{type:'error', error, stdout, stderr} on failure — and NO Bash exit-code
field exists in the payload at all. The handler only accepted string
responses, so on real Claude Code payloads output read as empty:
tests_passed never fired from the hook, and a FAILED git commit would
still award commit XP (empty output looked like success).
Now the object shape is parsed (error text included so ERROR_REGEX sees
real failures), with tests pinned to the documented payloads.
Flagged by buddy guard mode as an unchallenged assumption; the doc check
proved it half-wrong. Good golem.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
First entry: Runecore's unchallenged_chain detector questioned the PostToolUse payload claim, which turned out half-wrong and hiding an XP-award bug behind 132 passing tests. Format designed for future automation (share cards, world-site /catches page, build-in-public posts). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reuse: pending-events path derives from constants.ts (one owner for ~/.buddy). Simplification: cachedConfig() helper replaces the copy-pasted cfgCache guard; awardXp loop rewritten; dead regex alternatives merged (vercel, fly/flyctl); dead 'level_up' INSTANT entry replaced with a real mechanism — level-ups now force an instant flush via deps.instant (the PR promised instant level-up celebrations; now it's true, without double-emitting the server-derived level_up event). Efficiency: awardXpBatch does one SELECT + one UPDATE for a whole hook batch (was N pairs); streak query returns DISTINCT days (≤60 rows, was ~1,200); plaza streak flames computed once per frame, not per citizen. Altitude: resolveEventType arbitration lives in xp-classify; classification priority order now derives mechanically from XP_REWARDS; streak SQL owned by streaks.ts (checkStreakMilestone, one-line server call); INSTANT_WORLD_ EVENTS lives with the event-type definitions; plaza celebrations are a data-driven CELEBRATION_SPEC (level_up stays the lone bespoke branch). +6 tests (milestone checker, instant flush, day-string streaks). 138 green. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Command detection anchors to the executed program per shell segment: 'echo git commit' and output containing '12 passed' no longer award; tests_passed requires a recognized runner command AND passing output - Pending events: atomic rename-claim before read (concurrent hook appends survive), 15-minute age window, exact-replay dedupe, 10-event cap per consume - Self-report damper: summary-classified elevated events cap at 8/day (hook-verified events exempt) — the honor-system channel degrades to observe under spam instead of paying deploy rates - Streak window widened to 400 days so 60+ day streaks compute correctly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cherry-picked from Codex's parallel review pass — the one piece of its uncommitted alternative implementation kept; it pins the invalidation contract already shipped in the round-2 hardening. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mandEvent Prevent `echo 'x; git commit'` from splitting into a fake git-commit segment that bypasses the anchored PREFIX guard and farms commit XP. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Covers b6233db (quoted shell operators cannot fabricate command segments) and confirms quotes inside genuine commands stay detectable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
terpjwu1
added a commit
that referenced
this pull request
Jul 5, 2026
…mbed A 🎵 toggle summons a small corner player (youtube-nocookie, official embed — rights holders keep attribution/monetization). Strictly opt-in: no third-party request of any kind until clicked; toggling off removes the iframe entirely. aria-pressed + labels for screen readers. Smoke test drives the real flow in headless Chromium: no iframe before click, correct playlist after, clean removal on toggle-off. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #143. Fixes the dormant XP economy (commit/bug_fix/deploy rewards were defined but never fired — everything was flat 5 XP, making level 50 a ~21,000-observe grind) and wires the Buddy World incentive loop.
Detection channels — how the agent "knows":
git commitexit 0 → commit;wrangler deploy/npm publish→ deploy; "12 passed" with no failures → tests_passed). Events queue in~/.buddy/pending-events.jsonl(hooks stay native-dep-free) and the MCP server awards them on the next observe.classifySummary()on the buddy_observe summary covers bug_fix (no command signature) and hookless hosts. Hook wins on duplicates.Economy: observe 8 · session 5 · tests_passed 20 · commit 25 · bug_fix 35 · deploy 60 · +10% world blessing. Active day ≈ 700 XP → level 50 in months, not years. Curve untouched (world validates
level === levelFromXp(xp)across client versions).World loop: blessing for teleported buddies, instant sync flush for deploy/level-up/streak celebrations (~10s to fireworks), streak_7 milestones with a 🔥 flame by the name tag for a week, anti-abuse recalibrated (900/hr, 300 burst).
Test plan
tscclean, migration drift-guard regenerated (xp_bucket default 300)🤖 Generated with Claude Code