3 Commits

Author SHA1 Message Date
ranger c7d49b383a chore: release v0.1.2 — wink tuning entry
Documents the wink-probability tune-down (f661eab) as a proper
patch release. No code behaviour change in this commit — purely
version metadata, changelog, and user-facing about-page history.

CHANGES
- buddy.php: Version header + BUDDY_VERSION constant 0.1.1 → 0.1.2
- CHANGELOG.md: new [0.1.2] entry above [0.1.1], explains the
  tuning rationale + what's intentionally unchanged (wink visuals,
  trigger threshold mood >= 75)
- inc/about.php: version-history card leads with v0.1.2 (latest
  badge), v0.1.1 demoted to second slot

Why a patch release: the wink fires far less often now than it
did in v0.1.1. From a user's point of view that IS a behaviour
change worth a version. Following SemVer: PATCH bump because the
public API and feature set are unchanged; only the tuning of an
existing behaviour was adjusted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 07:20:25 +01:00
ranger f661eabba1 tune: lower wink probability from 30% to 5%
The original 30% per-render rate felt disturbing in practice. Default
mood is 80, so most admin/dashboard renders cleared the >=75 gate, and
~30% of those flipped to wink. Stacked across the main admin page +
dashboard widget visible on the same screen, the visible wink rate
felt closer to "stuck" than "playful" — buddy looked like he had one
eye closed all the time instead of occasionally cheeking out.

5% is true Easter-egg territory: rare enough to feel magical when it
lands, frequent enough you'll catch it after a few admin sessions.
Refresh ~20 times before expecting to see one.

CHANGES
- inc/state.php: mt_rand probability gate 30 -> 5
- inc/state.php: docstring updated to match new ~5% probability

NOT CHANGED
- Wink visuals (sprite.php) unchanged — still the same closed-eye arc,
  asymmetric smirk, rosier cheeks. Just rarer.
- Version constant + CHANGELOG entry left at v0.1.1 — this is a tuning
  hotfix, not new behavior worth a version bump. If we want a v0.1.2
  bump for hygiene, that's a separate commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 07:16:32 +01:00
ranger 8c38d38a3a feat: add winking expression (v0.1.1)
Buddy now has a fourth mood tone — wink — with one eye closed, an
asymmetric smirk, and rosier cheeks. Renders as a small variant
inside the existing inline-SVG sprite (still zero image files, no
new assets). When overall mood is >= 75, there's a 30% chance on
each page render that the wink replaces the standard happy face —
gives the pet a touch of unpredictable personality.

Why this commit exists: v0.1.0 had three tones (happy / neutral /
sad). Adding wink is the smallest possible demo that the SVG
expression engine is properly extensible — every future mood,
state, accessory or species can land via the same pattern. ~20
lines of PHP, ~2 lines of CSS, no bundle weight, no dependencies.

CHANGES
- inc/sprite.php: wink added to allowed-tones list. Left eye
  renders as a closed-eye arc instead of the open circle. Mouth
  shifts to an asymmetric smirk. Cheek opacity 0.55 → 0.75 for
  extra cheekiness.
- inc/state.php: buddy_mood_label() returns wink ~30% of the time
  when mood >= 75.
- assets/css/buddy.css: new .buddy-widget__mood--wink and
  .buddy-main__mood--wink rules — warm amber pill.
- About-page version-history leads with v0.1.1; v0.1.0 demoted.

VERSION
- buddy.php header 0.1.0 → 0.1.1
- BUDDY_VERSION constant 0.1.0 → 0.1.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 10:36:51 +01:00
6 changed files with 109 additions and 15 deletions
+65
View File
@@ -9,6 +9,71 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) — versi
--- ---
## [0.1.2] — 2026-05-26
### Tuned — Wink probability lowered from 30% to 5%
The wink Easter-egg added in v0.1.1 fired at 30% per page render
when Buddy's mood was ≥ 75. Default mood is 80, so most admin
visits hit the gate and ~30% of those flipped to wink. Stacked
across the main admin page + dashboard widget visible on the same
screen, Buddy ended up looking like he had one eye closed all the
time — "stuck" rather than "playful".
Dropped to 5%. Same wink visuals when it fires; just rare enough
to feel magical instead of constant. Refresh ~20 times when mood
is high and you'll catch one.
### Changed
- **`inc/state.php`**: `buddy_mood_label()` probability gate
`mt_rand( 1, 100 ) <= 30` changed to `<= 5`. Docstring updated
to reflect new ~5% rate.
- **Plugin version bumped**: header + `BUDDY_VERSION` constant
0.1.1 → 0.1.2.
- **About page** version-history card leads with v0.1.2; v0.1.1
demoted.
### Not changed
- Wink visuals (`inc/sprite.php`) — same closed-eye arc, smirk,
rosy cheeks when it fires. Just rarer.
- All other behavior identical to v0.1.1.
---
## [0.1.1] — 2026-05-25
### Added — Wink expression 😉
Buddy now has a fourth mood tone: **`wink`** — one eye closed, an
asymmetric smirk, and rosier cheeks. Rendered as a small variant
inside the existing inline-SVG sprite (still zero image files, no
new assets). When Buddy's overall mood is ≥ 75, there's a ~30%
chance on each page render that the wink replaces the standard
happy face. Refresh a few times when Buddy is content and you'll
catch it.
Why this commit exists: the v0.1.0 sprite had three tones
(happy / neutral / sad). Adding `wink` was the smallest possible
demo that the SVG expression engine is properly extensible — every
future mood/state/species can be added the same way. ~20 lines of
PHP, ~2 lines of CSS, no bundle weight, no dependencies.
### Changed
- **`inc/sprite.php`**: added `wink` to the allowed-tones list.
Left eye renders as a closed-eye curve (a small downward arc)
instead of the open circle. Right eye stays normal. Mouth shifts
to an asymmetric smirk curve. Cheek opacity bumped from 0.55 to
0.75 for extra cheekiness.
- **`inc/state.php`**: `buddy_mood_label()` now has a 30% chance of
returning the wink tone when the overall mood score is ≥ 75.
- **`assets/css/buddy.css`**: new `.buddy-widget__mood--wink` and
`.buddy-main__mood--wink` rules — warm amber pill matching the
cheeky vibe.
- **About page** version-history card leads with v0.1.1; v0.1.0
demoted to the previous entry.
- **Plugin version bumped**: header + `BUDDY_VERSION` constant
0.1.0 → 0.1.1.
---
## [0.1.0] — 2026-05-25 ## [0.1.0] — 2026-05-25
**Buddy is born.** First release of a new standalone WordPress plugin extracted-and-rebuilt from the tamagotchi feature that once lived inside A-WP-Notes v1.1.5 (now gracefully retired). Buddy stands on its own as a focused, charming companion plugin for the WordPress dashboard. **Buddy is born.** First release of a new standalone WordPress plugin extracted-and-rebuilt from the tamagotchi feature that once lived inside A-WP-Notes v1.1.5 (now gracefully retired). Buddy stands on its own as a focused, charming companion plugin for the WordPress dashboard.
+2
View File
@@ -57,6 +57,7 @@
vertical-align: middle; vertical-align: middle;
} }
.buddy-widget__mood--happy { background:#e8f5ea; color:#1b6f2d; } .buddy-widget__mood--happy { background:#e8f5ea; color:#1b6f2d; }
.buddy-widget__mood--wink { background:#fef3c7; color:#92400e; }
.buddy-widget__mood--neutral { background:#f0f0f1; color:#3c434a; } .buddy-widget__mood--neutral { background:#f0f0f1; color:#3c434a; }
.buddy-widget__mood--sad { background:#fcf0f1; color:#8a2424; } .buddy-widget__mood--sad { background:#fcf0f1; color:#8a2424; }
@@ -138,6 +139,7 @@
vertical-align: middle; vertical-align: middle;
} }
.buddy-main__mood--happy { background:#e8f5ea; color:#1b6f2d; } .buddy-main__mood--happy { background:#e8f5ea; color:#1b6f2d; }
.buddy-main__mood--wink { background:#fef3c7; color:#92400e; }
.buddy-main__mood--neutral { background:#f0f0f1; color:#3c434a; } .buddy-main__mood--neutral { background:#f0f0f1; color:#3c434a; }
.buddy-main__mood--sad { background:#fcf0f1; color:#8a2424; } .buddy-main__mood--sad { background:#fcf0f1; color:#8a2424; }
+2 -2
View File
@@ -5,7 +5,7 @@
* Plugin Name: Buddy * Plugin Name: Buddy
* Plugin URI: https://icanhelp.ie/buddy * Plugin URI: https://icanhelp.ie/buddy
* Description: Adopt a small companion that lives in your WordPress dashboard. Its mood reflects your site's health — published posts feed it, outdated plugins make it sick, clearing spam makes it happy. Gamifies WordPress maintenance with a bit of charm. * Description: Adopt a small companion that lives in your WordPress dashboard. Its mood reflects your site's health — published posts feed it, outdated plugins make it sick, clearing spam makes it happy. Gamifies WordPress maintenance with a bit of charm.
* Version: 0.1.0 * Version: 0.1.2
* Requires at least: 5.0 * Requires at least: 5.0
* Requires PHP: 7.4 * Requires PHP: 7.4
* Author: David Keane * Author: David Keane
@@ -20,7 +20,7 @@
if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! defined( 'ABSPATH' ) ) { exit; }
// Plugin coordinates. // Plugin coordinates.
if ( ! defined( 'BUDDY_VERSION' ) ) { define( 'BUDDY_VERSION', '0.1.0' ); } if ( ! defined( 'BUDDY_VERSION' ) ) { define( 'BUDDY_VERSION', '0.1.2' ); }
if ( ! defined( 'BUDDY_FILE' ) ) { define( 'BUDDY_FILE', __FILE__ ); } if ( ! defined( 'BUDDY_FILE' ) ) { define( 'BUDDY_FILE', __FILE__ ); }
if ( ! defined( 'BUDDY_PATH' ) ) { define( 'BUDDY_PATH', plugin_dir_path( __FILE__ ) ); } if ( ! defined( 'BUDDY_PATH' ) ) { define( 'BUDDY_PATH', plugin_dir_path( __FILE__ ) ); }
if ( ! defined( 'BUDDY_URL' ) ) { define( 'BUDDY_URL', plugin_dir_url( __FILE__ ) ); } if ( ! defined( 'BUDDY_URL' ) ) { define( 'BUDDY_URL', plugin_dir_url( __FILE__ ) ); }
+9 -1
View File
@@ -98,7 +98,15 @@ function buddy_render_about_page() {
<h2><?php esc_html_e( 'Version history', 'buddy' ); ?></h2> <h2><?php esc_html_e( 'Version history', 'buddy' ); ?></h2>
<ul> <ul>
<li> <li>
<span class="ver">v0.1.0</span> &mdash; 25 May 2026 <span class="latest">latest</span><br> <span class="ver">v0.1.2</span> &mdash; 26 May 2026 <span class="latest">latest</span><br>
<?php esc_html_e( 'Wink, tuned. The Easter-egg wink from v0.1.1 was firing at 30% per render — felt closer to "stuck" than "playful". Dropped to 5%: same cheeky face when it lands, just rare enough to feel like a treat.', 'buddy' ); ?>
</li>
<li>
<span class="ver">v0.1.1</span> &mdash; 25 May 2026<br>
<?php esc_html_e( 'Cheeky face! New wink expression that occasionally appears when Buddy is in a good mood — one eye closed, asymmetric smirk, rosier cheeks. Pure SVG, no image files. Proof that the expression engine is properly extensible.', 'buddy' ); ?>
</li>
<li>
<span class="ver">v0.1.0</span> &mdash; 25 May 2026<br>
<?php esc_html_e( 'First release. Phase A complete: Buddy exists. Dashboard widget + dedicated admin page show the SVG character, name, mood label, four stats bars. Self-hosted update checker wired up to Gitea from commit 1. No interactions yet — that\'s next.', 'buddy' ); ?> <?php esc_html_e( 'First release. Phase A complete: Buddy exists. Dashboard widget + dedicated admin page show the SVG character, name, mood label, four stats bars. Self-hosted update checker wired up to Gitea from commit 1. No interactions yet — that\'s next.', 'buddy' ); ?>
</li> </li>
</ul> </ul>
+19 -10
View File
@@ -23,14 +23,15 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
*/ */
function buddy_render_sprite( $species = 'default', $tone = 'happy', $size = 'md' ) { function buddy_render_sprite( $species = 'default', $tone = 'happy', $size = 'md' ) {
$species = sanitize_key( $species ); $species = sanitize_key( $species );
$tone = in_array( $tone, array( 'happy', 'neutral', 'sad' ), true ) ? $tone : 'happy'; $tone = in_array( $tone, array( 'happy', 'neutral', 'sad', 'wink' ), true ) ? $tone : 'happy';
$size = in_array( $size, array( 'sm', 'md', 'lg' ), true ) ? $size : 'md'; $size = in_array( $size, array( 'sm', 'md', 'lg' ), true ) ? $size : 'md';
// Mouth path varies by tone. // Mouth path varies by tone.
$mouth = array( $mouth = array(
'happy' => 'M 42 60 Q 50 70 58 60', // smile 'happy' => 'M 42 60 Q 50 70 58 60', // symmetric smile
'neutral' => 'M 42 64 L 58 64', // flat 'neutral' => 'M 42 64 L 58 64', // flat
'sad' => 'M 42 66 Q 50 58 58 66', // frown 'sad' => 'M 42 66 Q 50 58 58 66', // frown (curves up at edges)
'wink' => 'M 42 60 Q 50 70 58 62', // asymmetric smirk — right corner a touch higher
); );
$mouth_d = $mouth[ $tone ]; $mouth_d = $mouth[ $tone ];
@@ -46,10 +47,16 @@ function buddy_render_sprite( $species = 'default', $tone = 'happy', $size = 'md
<circle cx="50" cy="55" r="32" fill="<?php echo esc_attr( $body_fill ); ?>" stroke="#c9941d" stroke-width="2" /> <circle cx="50" cy="55" r="32" fill="<?php echo esc_attr( $body_fill ); ?>" stroke="#c9941d" stroke-width="2" />
<!-- left eye --> <!-- left eye -->
<g class="buddy-sprite__eye buddy-sprite__eye--left"> <g class="buddy-sprite__eye buddy-sprite__eye--left">
<circle cx="40" cy="46" r="5" fill="#2c3338" /> <?php if ( $tone === 'wink' ) : ?>
<circle cx="41.2" cy="45" r="1.5" fill="#fff" /> <!-- Closed left eye for a wink: a downward curved line below the eye-circle's normal y. -->
<path d="M 35 46 Q 40 50 45 46"
stroke="#2c3338" stroke-width="2.4" fill="none" stroke-linecap="round" />
<?php else : ?>
<circle cx="40" cy="46" r="5" fill="#2c3338" />
<circle cx="41.2" cy="45" r="1.5" fill="#fff" />
<?php endif; ?>
</g> </g>
<!-- right eye --> <!-- right eye (always open, even during wink) -->
<g class="buddy-sprite__eye buddy-sprite__eye--right"> <g class="buddy-sprite__eye buddy-sprite__eye--right">
<circle cx="60" cy="46" r="5" fill="#2c3338" /> <circle cx="60" cy="46" r="5" fill="#2c3338" />
<circle cx="61.2" cy="45" r="1.5" fill="#fff" /> <circle cx="61.2" cy="45" r="1.5" fill="#fff" />
@@ -57,10 +64,12 @@ function buddy_render_sprite( $species = 'default', $tone = 'happy', $size = 'md
<!-- mouth --> <!-- mouth -->
<path d="<?php echo esc_attr( $mouth_d ); ?>" <path d="<?php echo esc_attr( $mouth_d ); ?>"
stroke="#2c3338" stroke-width="2" fill="none" stroke-linecap="round" /> stroke="#2c3338" stroke-width="2" fill="none" stroke-linecap="round" />
<!-- cheeks (only when happy or neutral) --> <!-- cheeks: not on the sad face; extra-rosy on the wink (cheeky vibe) -->
<?php if ( $tone !== 'sad' ) : ?> <?php if ( $tone !== 'sad' ) :
<circle cx="33" cy="58" r="3" fill="#f4866a" opacity="0.55" /> $cheek_opacity = ( $tone === 'wink' ) ? '0.75' : '0.55';
<circle cx="67" cy="58" r="3" fill="#f4866a" opacity="0.55" /> ?>
<circle cx="33" cy="58" r="3" fill="#f4866a" opacity="<?php echo esc_attr( $cheek_opacity ); ?>" />
<circle cx="67" cy="58" r="3" fill="#f4866a" opacity="<?php echo esc_attr( $cheek_opacity ); ?>" />
<?php endif; ?> <?php endif; ?>
<!-- tiny feet --> <!-- tiny feet -->
<ellipse cx="42" cy="88" rx="6" ry="3" fill="#c9941d" /> <ellipse cx="42" cy="88" rx="6" ry="3" fill="#c9941d" />
+12 -2
View File
@@ -101,10 +101,20 @@ function buddy_overall_mood( array $state ) {
} }
/** /**
* Pick a one-word emoji / status label based on overall mood. Pure * Pick a one-word status label + sprite tone based on overall mood.
* cosmetic, used in the dashboard widget header. * Pure cosmetic, used in the dashboard widget header and the main
* admin page.
*
* Easter-egg: when Buddy is genuinely happy (mood >= 75) there's a
* ~5% chance per page-render of returning the "Cheeky" wink tone
* instead of the standard happy face. Rare enough to feel magical
* rather than disturbing — refresh the page a few dozen times and
* you'll catch it.
*/ */
function buddy_mood_label( $mood_score ) { function buddy_mood_label( $mood_score ) {
if ( $mood_score >= 75 && mt_rand( 1, 100 ) <= 5 ) {
return array( 'label' => __( 'Cheeky 😉', 'buddy' ), 'tone' => 'wink' );
}
if ( $mood_score >= 80 ) { return array( 'label' => __( 'Thriving', 'buddy' ), 'tone' => 'happy' ); } if ( $mood_score >= 80 ) { return array( 'label' => __( 'Thriving', 'buddy' ), 'tone' => 'happy' ); }
if ( $mood_score >= 60 ) { return array( 'label' => __( 'Content', 'buddy' ), 'tone' => 'happy' ); } if ( $mood_score >= 60 ) { return array( 'label' => __( 'Content', 'buddy' ), 'tone' => 'happy' ); }
if ( $mood_score >= 40 ) { return array( 'label' => __( 'Okay', 'buddy' ), 'tone' => 'neutral' ); } if ( $mood_score >= 40 ) { return array( 'label' => __( 'Okay', 'buddy' ), 'tone' => 'neutral' ); }