NAME

Developer::Dashboard::IndicatorStore - file-backed indicator state for Developer Dashboard

SYNOPSIS

my $store = Developer::Dashboard::IndicatorStore->new(paths => $paths);
$store->set_indicator('docker', status => 'ok');

DESCRIPTION

This module stores small status indicators that are consumed by prompt rendering and dashboard views. It also provides a small built-in refresh path for core generic indicators.

METHODS

new, set_indicator, get_indicator, list_indicators, _sort_indicators, _indicator_sort_order_cmp, collector_indicator_candidate

Construct and manage the indicator store.

list_indicators reads current records from the ordered runtime roots and returns them in priority/collector/name order. When at least 32 records are present, its private sorter decorates each item with those comparison fields once, then sorts the compact tuples to avoid repeated method calls and hash lookups in the comparator. The small-list path continues to use the shared comparison method. Both paths use the same field defaults and tie rules. _indicator_sort_order_cmp compares decorated tuples without object method dispatch; direct tests pin each priority, collector-order, and name-fallback case.

sync_collectors discovers its ordered indicator roots once and shares them with all collector comparisons and the final inventory. It also decodes each status file at most once during that synchronization. The cache is local to the call; writes and deletions invalidate the affected file, and a later sync rereads disk so external edits remain visible. Docker regression coverage checks root discovery, physical file reads, next-sync freshness, and collector retirement. With 50 configured collectors, a byte-identical Docker comparison measured 9.203 ms/request before and 2.689 ms/request after (3.42x). NYTProf showed status-file reads dropping from 15,000 to 5,000 and root resolutions from 15,100 to 100 over 100 requests. This workload-specific gain does not establish Problem 48's 50x target for every routine.

mark_stale, is_stale, refresh_core_indicators, page_header_items, page_header_payload

Handle stale state and refresh the local project and Git indicators. Docker is not a built-in indicator; its status is shown only when a collector is configured for Docker. Core refresh also removes persisted records matching the retired built-in Docker signature while preserving customized and collector-managed records named docker.

PURPOSE

This module persists prompt and browser status indicators. It stores indicator definitions and live status updates, merges collector-managed indicators with user-managed ones, keeps TT-backed collector icon templates separate from their live rendered icon values, refreshes project/Git core state without probing Docker, retires old built-in Docker records without deleting configured collector indicators, and provides the ordered indicator data used by the prompt renderer and the browser status strip.

WHY IT EXISTS

It exists because indicators are shared state that multiple features read and write. Prompt rendering, collector status, and browser chrome all need one source of truth for icon, label, priority, prompt visibility, and current status. set_indicator persists that state through Developer::Dashboard::PathRegistry::atomic_write_secure via an unpredictable per-writer staging path (DD-989), so a local actor cannot pre-plant a symlink at a known staging location and clobber an unrelated file.

WHEN TO USE

Use this file when changing indicator JSON layout, sorting rules, collector-managed indicator behavior, TT-backed collector icon persistence, core project/Git status refresh, or the persistence semantics of prompt-visible versus hidden indicators. Core refresh must not check for Docker or create a Docker indicator; explicitly configured Docker collectors remain supported.

HOW TO USE

Construct it with the active runtime paths, then call the store and list methods rather than editing indicator state files directly. Collector code should report into this store instead of inventing its own indicator persistence.

WHAT USES IT

It is used by the indicator command helper, by collector refresh paths, by the prompt renderer, by the browser status page, and by regression tests that verify indicator ownership and ordering.

EXAMPLES

Example 1:

perl -Ilib -MDeveloper::Dashboard::IndicatorStore -e 1

Do a direct compile-and-load check against the module from a source checkout.

Example 2:

prove -lv t/02-indicator-collector.t

Run the focused regression tests that most directly exercise this module's behavior.

Example 3:

HARNESS_PERL_SWITCHES=-MDevel::Cover prove -lr t

Recheck the module under the repository coverage gate rather than relying on a load-only probe.

Example 4:

prove -lr t

Put any module-level change back through the entire repository suite before release.