Skip to content

Status: Implement StatusProviderFactory for ${status.*} ABML variable namespace #718

Description

@DonLoquacious

Feature: StatusProviderFactory for ${status.*} ABML namespace

Source: docs/plugins/STATUS.md § Potential Extensions (AUDIT:CONFIRMED 2026-03-25)

Summary

Implement IVariableProviderFactory for the ${status.*} ABML namespace, enabling NPCs to perceive their own active status effects in behavior expressions. This is the 15th variable provider and closes the NPC intelligence stack gap identified in VISION.md.

Why This Is Critical

The divine blessing feedback loop requires this:

  1. Divine god-actors observe NPC behavior → spend divinity on blessings
  2. Blessings are granted as Status effects via GrantStatusAsync
  3. GAP: Actor's ABML cannot see the effects → NPC behavior doesn't react
  4. Without reaction, the feedback loop doesn't close

Every other data-providing L4 service (Personality, Encounters, History, Faction, Obligation) already has a variable provider. Status is the missing piece.

Implementation Plan

Follows the established pattern (14 existing implementations):

Step 1: Schema

Add status provider to schemas/variable-providers.yaml:

status:
  service: Status
  purpose: "Active status effects for ABML behavioral decisions (${status.*}) — effect presence, stack counts, category counts"

Step 2: Generate

python3 scripts/generate-variable-providers.py

Adds Status constant and metadata to VariableProviderDefinitions.cs.

Step 3: Implement

plugins/lib-status/Providers/StatusProviderFactory.cs:

[BannouHelperService("status-provider", typeof(IStatusService), typeof(IVariableProviderFactory), lifetime: ServiceLifetime.Singleton)]
public sealed class StatusProviderFactory : IVariableProviderFactory
{
    public string ProviderName => VariableProviderDefinitions.Status;
    
    public async Task<IVariableProvider> CreateAsync(
        Guid? characterId, Guid realmId, Guid? locationId, CancellationToken ct)
    {
        if (!characterId.HasValue) return StatusVariableProvider.Empty;
        // Load from existing GetOrBuildActiveCacheAsync infrastructure
        // Use VariableProviderCacheBucket for per-entity caching
    }
}

plugins/lib-status/Providers/StatusVariableProvider.cs:

Proposed Variables

Expression Type Source
${status.active_count} int Total active item-based statuses
${status.has.<code>} bool Whether entity has a specific status template code active
${status.stacks.<code>} int Stack count for a specific status (0 if not present)
${status.category_count.<category>} int Count of active statuses in a category (buff, debuff, death, etc.)
${status.has_category.<category>} bool Whether any status in the category is active

All variables are qualitative behavioral data — presence, counts, categories. Magnitudes and damage numbers are game-server math (resolved in STATUS.md § tick-based effects and effect magnitude computation).

Data Source

GetOrBuildActiveCacheAsync — the existing Redis cache (60s TTL) that already backs all Status query endpoints. No new state stores or queries needed.

Reference Implementations

  • plugins/lib-character-personality/Providers/PersonalityProviderFactory.cs (L4, same layer)
  • plugins/lib-obligation/Providers/ObligationProviderFactory.cs (L4, same layer)
  • plugins/lib-faction/Providers/FactionProviderFactory.cs (L4, same layer with cache bucket)

Acceptance Criteria

  • status added to schemas/variable-providers.yaml
  • VariableProviderDefinitions.Status constant generated
  • StatusProviderFactory implements IVariableProviderFactory
  • StatusVariableProvider resolves all proposed ${status.*} expressions
  • Uses VariableProviderCacheBucket for per-entity caching
  • Empty provider returned for null characterId
  • Unit tests for provider factory and variable resolution

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions