Today AwardSkillCommandHandler writes the EarnedSkill and returns — no server UserActivity is emitted, and the registry's skill-earned action is a client breadcrumb the RewardEngine deliberately ignores (KnowledgeDomainRegistry.cs:799). So no staff rule can pay out for earning a skill.
Emit a server-side UserActivity (source server, domain Learning, new action skill-awarded, metadata: skillDefinitionId, tier, interestAreaId) from AwardSkillCommandHandler after the insert. Award-only — nothing on revoke.
Register skill-awarded in KnowledgeDomainRegistry as a trustworthy server action (kept distinct from the skill-earned breadcrumb).
New IRewardStateProvider key earned-skill-count (pattern: wishlist-country-count etc.) enabling threshold state conditions ("has ≥N skills / ≥N gold skills").
Tests: activity emitted on award; RewardEngine matches a skill-awarded rule end-to-end (completion + FundEarning donation); metadata condition on tier works.
Result: staff can create "earn a gold skill → $X toward your dream destination" rules in the existing admin → sponsorship-management → Location funds page.
Part of #868 (PR-7, backend).
Today `AwardSkillCommandHandler` writes the `EarnedSkill` and returns — no server `UserActivity` is emitted, and the registry's `skill-earned` action is a client breadcrumb the RewardEngine deliberately ignores (`KnowledgeDomainRegistry.cs:799`). So no staff rule can pay out for earning a skill.
- Emit a server-side `UserActivity` (source `server`, domain `Learning`, new action `skill-awarded`, metadata: `skillDefinitionId`, `tier`, `interestAreaId`) from `AwardSkillCommandHandler` after the insert. Award-only — nothing on revoke.
- Register `skill-awarded` in `KnowledgeDomainRegistry` as a trustworthy server action (kept distinct from the `skill-earned` breadcrumb).
- New `IRewardStateProvider` key `earned-skill-count` (pattern: `wishlist-country-count` etc.) enabling threshold state conditions ("has ≥N skills / ≥N gold skills").
- Tests: activity emitted on award; RewardEngine matches a `skill-awarded` rule end-to-end (completion + FundEarning donation); metadata condition on `tier` works.
Result: staff can create "earn a gold skill → $X toward your dream destination" rules in the existing admin → sponsorship-management → Location funds page.
Audited against origin/master — implementation is complete; the required tests are not. Staying open on tests only. (The standalone PR #496 was closed unmerged; the work landed via consolidated backend PR #497.)
Landed
SpikerSoft.Business/Domain/Skills/SkillAwardedActivity.cs:20-41 — domain learning.skills, action skill-awarded, Source = "server", all three metadata keys (skillDefinitionId, tier, interestAreaId).
Emitted post-insert on both award paths: AwardSkillCommandHandler.cs:57 and CheckAutoAwardsCommandHandler.cs:116. Revoke correctly emits nothing.
KnowledgeDomainRegistry.cs:577 — new("skill-awarded", "Skill Awarded", "Learning", false), server-trustworthy, kept distinct from the client-side skill-earned breadcrumb at :820.
Provider IRewardStateProvider.cs:51-58Key => "earned-skill-count", DI-registered at ServiceCollectionExtensions.cs:625.
Missing — 2 of the 3 required test items, plus provider coverage:
No RewardEngine end-to-end test that a skill-awarded rule matches and produces a completion + FundEarning. git grep -rn "skill-awarded|SkillAwardedActivity" origin/master -- '*Tests*' hits only AwardSkillCommandHandlerTests.cs and CheckAutoAwardsCommandHandlerTests.cs — nothing in SpikerSoft.Business.Tests/Domain/Funds/RewardEngineMatchingTests.cs.
No metadata-condition-on-tier test — git grep -rn '"tier"' origin/master -- 'SpikerSoft.Business.Tests/Domain/Funds/' returns nothing.
No coverage for EarnedSkillCountProvider — git grep -rn "earned-skill-count|EarnedSkillCountProvider" origin/master -- '*Tests*' returns nothing.
Worth weighting this properly: the untested path disburses real money, and the epic's manual "rewards smoke test" is also unrecorded, so as far as the tracker shows the payout path has been verified neither in automation nor in production. I'd treat the two engine tests as blocking rather than nice-to-have.
Audited against `origin/master` — **implementation is complete; the required tests are not.** Staying open on tests only. (The standalone PR #496 was closed unmerged; the work landed via consolidated backend PR #497.)
**Landed**
- `SpikerSoft.Business/Domain/Skills/SkillAwardedActivity.cs:20-41` — domain `learning.skills`, action `skill-awarded`, `Source = "server"`, all three metadata keys (`skillDefinitionId`, `tier`, `interestAreaId`).
- Emitted post-insert on both award paths: `AwardSkillCommandHandler.cs:57` and `CheckAutoAwardsCommandHandler.cs:116`. Revoke correctly emits nothing.
- `KnowledgeDomainRegistry.cs:577` — `new("skill-awarded", "Skill Awarded", "Learning", false)`, server-trustworthy, kept distinct from the client-side `skill-earned` breadcrumb at `:820`.
- Provider `IRewardStateProvider.cs:51-58` `Key => "earned-skill-count"`, DI-registered at `ServiceCollectionExtensions.cs:625`.
**Missing — 2 of the 3 required test items, plus provider coverage:**
1. No RewardEngine end-to-end test that a `skill-awarded` rule matches and produces a completion + FundEarning. `git grep -rn "skill-awarded|SkillAwardedActivity" origin/master -- '*Tests*'` hits only `AwardSkillCommandHandlerTests.cs` and `CheckAutoAwardsCommandHandlerTests.cs` — nothing in `SpikerSoft.Business.Tests/Domain/Funds/RewardEngineMatchingTests.cs`.
2. No metadata-condition-on-`tier` test — `git grep -rn '"tier"' origin/master -- 'SpikerSoft.Business.Tests/Domain/Funds/'` returns nothing.
3. No coverage for `EarnedSkillCountProvider` — `git grep -rn "earned-skill-count|EarnedSkillCountProvider" origin/master -- '*Tests*'` returns nothing.
Worth weighting this properly: the untested path **disburses real money**, and the epic's manual "rewards smoke test" is also unrecorded, so as far as the tracker shows the payout path has been verified neither in automation nor in production. I'd treat the two engine tests as blocking rather than nice-to-have.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #868 (PR-7, backend).
Today
AwardSkillCommandHandlerwrites theEarnedSkilland returns — no serverUserActivityis emitted, and the registry'sskill-earnedaction is a client breadcrumb the RewardEngine deliberately ignores (KnowledgeDomainRegistry.cs:799). So no staff rule can pay out for earning a skill.UserActivity(sourceserver, domainLearning, new actionskill-awarded, metadata:skillDefinitionId,tier,interestAreaId) fromAwardSkillCommandHandlerafter the insert. Award-only — nothing on revoke.skill-awardedinKnowledgeDomainRegistryas a trustworthy server action (kept distinct from theskill-earnedbreadcrumb).IRewardStateProviderkeyearned-skill-count(pattern:wishlist-country-countetc.) enabling threshold state conditions ("has ≥N skills / ≥N gold skills").skill-awardedrule end-to-end (completion + FundEarning donation); metadata condition ontierworks.Result: staff can create "earn a gold skill → $X toward your dream destination" rules in the existing admin → sponsorship-management → Location funds page.
Audited against
origin/master— implementation is complete; the required tests are not. Staying open on tests only. (The standalone PR #496 was closed unmerged; the work landed via consolidated backend PR #497.)Landed
SpikerSoft.Business/Domain/Skills/SkillAwardedActivity.cs:20-41— domainlearning.skills, actionskill-awarded,Source = "server", all three metadata keys (skillDefinitionId,tier,interestAreaId).AwardSkillCommandHandler.cs:57andCheckAutoAwardsCommandHandler.cs:116. Revoke correctly emits nothing.KnowledgeDomainRegistry.cs:577—new("skill-awarded", "Skill Awarded", "Learning", false), server-trustworthy, kept distinct from the client-sideskill-earnedbreadcrumb at:820.IRewardStateProvider.cs:51-58Key => "earned-skill-count", DI-registered atServiceCollectionExtensions.cs:625.Missing — 2 of the 3 required test items, plus provider coverage:
skill-awardedrule matches and produces a completion + FundEarning.git grep -rn "skill-awarded|SkillAwardedActivity" origin/master -- '*Tests*'hits onlyAwardSkillCommandHandlerTests.csandCheckAutoAwardsCommandHandlerTests.cs— nothing inSpikerSoft.Business.Tests/Domain/Funds/RewardEngineMatchingTests.cs.tiertest —git grep -rn '"tier"' origin/master -- 'SpikerSoft.Business.Tests/Domain/Funds/'returns nothing.EarnedSkillCountProvider—git grep -rn "earned-skill-count|EarnedSkillCountProvider" origin/master -- '*Tests*'returns nothing.Worth weighting this properly: the untested path disburses real money, and the epic's manual "rewards smoke test" is also unrecorded, so as far as the tracker shows the payout path has been verified neither in automation nor in production. I'd treat the two engine tests as blocking rather than nice-to-have.