Class: Ucode::Glyphs::UniversalSet::CoverageReport

Inherits:
Object
  • Object
show all
Includes:
Idempotency
Defined in:
lib/ucode/glyphs/universal_set/coverage_report.rb

Overview

Standalone emitter for the universal-set coverage reports described by TODO 31 §Per-tier / §Per-block / §Gap investigation. Reads a Models::UniversalSetManifest and produces three JSON files under <output_root>/reports/:

  • by_tier.json — manifest.by_tier verbatim (tier-1 => N, pillar-1 => N, ...). Quick "how much of the set is real fonts vs. tofu?" answer.

  • by_block.json — per-block per-tier breakdown:

    { "Sidetic": { "assigned": 26, "tier-1": 26,
                  "pillar-1": 0, "pillar-2": 0, "pillar-3": 0 } }
    

    assigned is the count of manifest entries whose codepoint falls in this block (via Database#lookup_block). Each tier key counts the entries that resolved at that tier.

  • gaps.json — array of { codepoint, block, reason } for every manifest entry at pillar-3. These are the "tofu leaks" TODO 31 calls out as actionable curation follow-ups (excluding the documented-residual cases: unassigned, PUA, noncharacter — those are correctly Last Resort).

An optional failures: payload (from ManifestAccumulator#failures) writes a fourth file, failures.json, with per-codepoint exception log. Kept separate from gaps.json so the two concepts (tofu vs. crash) don't collide.

All writes are atomic via Idempotency. Re-running on an unchanged manifest is a no-op modulo nothing — JSON output is stable (sorted keys, deterministic ordering).

Instance Method Summary collapse

Methods included from Idempotency

#by_block_report_path, #by_tier_report_path, #gaps_report_path, #glyph_path, #manifest_path, #write_glyph

Methods included from Repo::AtomicWrites

#same_content?, #to_pretty_json, #write_atomic

Constructor Details

#initialize(output_root, database:) ⇒ CoverageReport

Returns a new instance of CoverageReport.

Parameters:

  • output_root (String, Pathname)

    directory holding manifest.json + reports/.

  • database (Ucode::Database)

    used for codepoint → block lookup. The report CLI command opens one for the target Unicode version; tests pass a small in-memory database.



56
57
58
59
# File 'lib/ucode/glyphs/universal_set/coverage_report.rb', line 56

def initialize(output_root, database:)
  @output_root = Pathname.new(output_root)
  @database = database
end

Instance Method Details

#emit(manifest, failures: []) ⇒ Hash

Write the three coverage reports. Returns the structured payload so callers (CLI) can render a summary without re-reading the files.

Parameters:

Returns:

  • (Hash)

    { by_tier:, by_block:, gaps:, failures:, by_tier_path:, by_block_path:, gaps_path:, failures_path: }



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/ucode/glyphs/universal_set/coverage_report.rb', line 71

def emit(manifest, failures: [])
  by_tier = manifest.by_tier
  by_block = build_by_block(manifest)
  gaps = build_gaps(manifest)

  by_tier_path = by_tier_report_path(@output_root)
  by_block_path = by_block_report_path(@output_root)
  gaps_path = gaps_report_path(@output_root)
  write_atomic(by_tier_path, to_pretty_json(by_tier))
  write_atomic(by_block_path, to_pretty_json(by_block))
  write_atomic(gaps_path, to_pretty_json(gaps))
  failures_path = write_failures(failures)

  {
    by_tier: by_tier,
    by_block: by_block,
    gaps: gaps,
    failures: failures,
    by_tier_path: by_tier_path,
    by_block_path: by_block_path,
    gaps_path: gaps_path,
    failures_path: failures_path,
  }
end