Module: GovCodes::AFSC::Releases

Defined in:
lib/gov_codes/afsc/releases.rb

Overview

Loads the versioned release manifest and per-release specialty index for a publication (DAFECD enlisted, DAFOCD officer), and resolves the release in effect on a given date. Both publications share this resolve/merge/cache machinery and are resolved independently (their release dates may diverge).

See docs/plans/2026-07-08-afsc-pdf-representation-design.md "Versioning by document release".

Storage layout (per release):

lib/gov_codes/afsc/releases.yml                          # manifest
lib/gov_codes/afsc/releases/dafecd/<date>/enlisted.yml   # enlisted index
lib/gov_codes/afsc/releases/dafocd/<date>/officer.yml    # officer index

Resolution: releases are sorted ascending by effective_date. A given as_of resolves to the release with the greatest effective_date <= as_of; as_of: nil resolves it as of today. A release only takes effect on its own effective_date -- a release dated in the future (e.g. one a consumer pre-loads ahead of its official date, see DEC-004 below) is not resolved until that date arrives, even though it is the most recently added one. A date before the earliest shipped release resolves to no release (an empty index / nil date).

Extensibility (DEC-004): both tiers merge across the load path (gem lib dir first, then the load path). The manifest's per-publication release list is unioned by effective_date -- a consumer releases.yml ADDS releases without hiding the shipped ones, and a same-date entry from the load path wins. For the resolved release, the release index found at each lookup path is merged, so a consumer may drop gov_codes/afsc/releases/dafecd//enlisted.yml to extend or override the shipped index.

Constant Summary collapse

ENLISTED_PUBLICATION =

Publication key for the enlisted directory (DAFECD).

"dafecd"
OFFICER_PUBLICATION =

Publication key for the officer directory (DAFOCD).

"dafocd"

Class Method Summary collapse

Class Method Details

.effective_date_for(as_of: nil, lookup: $LOAD_PATH, publication: ENLISTED_PUBLICATION) ⇒ Object

Resolve the effective date for publication (defaults to enlisted). Publications are resolved independently: an officer release date never moves the enlisted latest date and vice versa.



67
68
69
70
# File 'lib/gov_codes/afsc/releases.rb', line 67

def effective_date_for(as_of: nil, lookup: $LOAD_PATH, publication: ENLISTED_PUBLICATION)
  release = resolve_release(publication, as_of: as_of, lookup: lookup)
  release && release[:date]
end

.enlisted_index(as_of: nil, lookup: $LOAD_PATH) ⇒ Object



46
47
48
# File 'lib/gov_codes/afsc/releases.rb', line 46

def enlisted_index(as_of: nil, lookup: $LOAD_PATH)
  release_index(ENLISTED_PUBLICATION, "enlisted.yml", as_of: as_of, lookup: lookup)
end

.manifest(lookup: $LOAD_PATH) ⇒ Object



42
43
44
# File 'lib/gov_codes/afsc/releases.rb', line 42

def manifest(lookup: $LOAD_PATH)
  manifest_cache[cache_key(lookup)] ||= load_manifest(lookup)
end

.officer_index(as_of: nil, lookup: $LOAD_PATH) ⇒ Object



50
51
52
# File 'lib/gov_codes/afsc/releases.rb', line 50

def officer_index(as_of: nil, lookup: $LOAD_PATH)
  release_index(OFFICER_PUBLICATION, "officer.yml", as_of: as_of, lookup: lookup)
end

.reset!Object



72
73
74
75
# File 'lib/gov_codes/afsc/releases.rb', line 72

def reset!
  @manifest_cache = {}
  @index_cache = {}
end

.ri_index(as_of: nil, lookup: $LOAD_PATH, publication: ENLISTED_PUBLICATION) ⇒ Object

Resolve the RI/SDI index for publication (enlisted DAFECD or officer DAFOCD). RI/SDI codes live in both directories with different code grammars (5-char enlisted, 4-char officer), so this wrapper is parameterized by publication; it otherwise reuses the same resolve/ merge/cache and acronym-overlay machinery as enlisted_index/ officer_index.



60
61
62
# File 'lib/gov_codes/afsc/releases.rb', line 60

def ri_index(as_of: nil, lookup: $LOAD_PATH, publication: ENLISTED_PUBLICATION)
  release_index(publication, "ri.yml", as_of: as_of, lookup: lookup)
end