Area: Engagement (audit p9) · Surface: /achievements, /achievements/{slug}, AchievementController · Dimension: competitor-gap · Severity: major
Locked achievements give zero feedback on how close a member is. A user with 9 posts and one with 0 posts both see the identical locked 'ten_posts' card. Skool, Circle, and Discourse all show progress toward the next tier ('7/10 posts', progress rings, 'next badge in 2 replies'). Progress visibility is one of the strongest pull mechanics in community gamification because it converts a vague goal into a concrete near-miss that drives the next action. We already compute the raw counts server-side in checkAndGrant — we throw them away instead of rendering 'N / threshold' and a progress bar on each locked card.
Evidence
Achievement::checkAndGrant() (src/Models/Achievement.php:315-384) computes each condition as a boolean (e.g. 'ten_posts' => $postCount >= 10) and grants on true — no count is ever persisted or surfaced. The achievements table schema has only slug/name/description/icon/category (database/schema.sql:72-80) — no threshold/goal/progress columns. The card template (templates/achievements/index.php:156-172) renders only earner-count, earner-pct, rarity, and an is_earned check mark; there is no progress bar. The detail page (templates/achievements/users.php:19-42) shows description + earners, never 'your progress' or 'how to earn it'.
Suggested fix. Add a nullable threshold (or goal_count) column to achievements, and have checkAndGrant return per-slug current/target so the catalog can render a progress bar + 'N of M' on locked cards and a 'You: 9/10' line on the detail page. The counts are already queried; only persistence + display is missing.
Filed by the automated tenant-app audit and adversarially evidence-verified. Status: verified. Open — not yet actioned.
Patrick Bass
@mobieus