mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-15 10:43:07 +00:00
Generaliza aditivamente o pipeline C186 (default município; specs verdes) via o descritor scripts/lib/dossieUnit.mjs (municipality|institution), extrai o emit A4/fit-guard para scripts/lib/buildPdf.mjs e a receita read-only para scripts/lib/readOnlyExtract.mjs. - Catálogo fail-closed src/lib/institutionCatalog.ts + institutionNameAliases.ts (seed UFBA/Correios/Enfermagem; escape one-off --slug/--name; dedup). - Skill/command/subagente /dossie-solla-instituicao; eras A/B/C reusadas. - Abrangência instituição × setor × rede nunca somada; era sem fonte vira página de lacuna explícita; lista capada declara "e mais N" (regra C188 no dono). - Boletim modelo 1×A4 com fase junto ao valor, sem fontes, sem CTA; herda apenas fatos com fonte do dossiê (incl. falas do acervo read-only). - Sem schema/migration/DB write; artefatos gitignored.
49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
import {
|
|
type InstitutionCatalogEntry,
|
|
institutionCatalog,
|
|
institutionSpellings,
|
|
} from '@/lib/institutionCatalog'
|
|
import { normalizeSearchPhrase } from '@/lib/wordStartFilter'
|
|
|
|
/**
|
|
* Institution-name resolution for the institutional dossiê (C187). Mirrors the
|
|
* `resolveMunicipalityName` fold: accent/case/punctuation-insensitive lookup
|
|
* over the catalog's canonical name + aliases. Returns null when unknown — the
|
|
* caller keeps the fail-closed policy (skill resolves aliases, never invents a
|
|
* slug). A fold shared by two different entries is treated as ambiguous (null),
|
|
* so the operator must pass the canonical slug.
|
|
*/
|
|
|
|
const entriesBySearchValue = new Map<string, Set<InstitutionCatalogEntry>>()
|
|
|
|
const register = (spelling: string, entry: InstitutionCatalogEntry) => {
|
|
const key = normalizeSearchPhrase(spelling)
|
|
if (!key) return
|
|
const bucket = entriesBySearchValue.get(key)
|
|
if (bucket) bucket.add(entry)
|
|
else entriesBySearchValue.set(key, new Set([entry]))
|
|
}
|
|
|
|
for (const entry of institutionCatalog) {
|
|
register(entry.slug, entry)
|
|
for (const spelling of institutionSpellings(entry)) register(spelling, entry)
|
|
}
|
|
|
|
/**
|
|
* Resolve a token (slug, canonical name or alias) to its catalog entry. Returns
|
|
* null when unknown or when the fold is ambiguous.
|
|
*/
|
|
export const resolveInstitutionEntry = (
|
|
value: string | undefined | null,
|
|
): InstitutionCatalogEntry | null => {
|
|
if (typeof value !== 'string') return null
|
|
const trimmed = value.trim()
|
|
if (!trimmed) return null
|
|
const bucket = entriesBySearchValue.get(normalizeSearchPhrase(trimmed))
|
|
if (!bucket || bucket.size !== 1) return null
|
|
return [...bucket][0] ?? null
|
|
}
|
|
|
|
/** Canonical name for a token, or null when unknown/ambiguous. */
|
|
export const resolveInstitutionName = (value: string | undefined | null): string | null =>
|
|
resolveInstitutionEntry(value)?.name ?? null
|