Shared referential quality policy¶
lexi-referential-v1 owns the rules used by HRX's Jobs, Skills and Job–Skills
tabs and the generated-skills workflow. It requires no Supabase dependency and
persists no referential data. HRX owns authentication, organization authorization,
pagination, storage, dismissed recommendations and human approvals.
Analyze an authorized snapshot¶
POST /lexi/api/v1/referentials/analyze requires the existing Lexi API key.
Provide complete jobs, skills, requirements, referentials,
validated_job_ids, optional dgi_ratio/dgi_available and duplicate exclusions.
Use referential_id=null for the organization-wide view. Duplicate identifiers,
missing association endpoints and unknown versions are rejected. The shared
input-safety budgets apply; oversized requests fail rather than being sampled.
checks="deterministic" evaluates rules and exact/fuzzy duplicates without
model calls. checks="semantic" separately enriches global duplicate groups
through candidate embeddings followed by OpenAI Decisions. Responses expose policy_version,
status, unavailable_checks, issues, policy, duplicate_metrics and the
three tab projections. Stable rule identifiers are independent of translations.
An empty, complete referential is distinct from an unavailable analysis. Malformed
internal tab projections fail explicitly rather than silently discarding findings.
Semantic processing embeds each distinct label once, using tasks of up to 512
labels (LEXI_SEMANTIC_EMBEDDING_CHUNK_SIZE, at most 2,048 provider inputs).
Jobs and skills share bounded embedding concurrency
(LEXI_SEMANTIC_EMBEDDING_CONCURRENCY, default 16). There is no 10,000-label cap.
Candidate retrieval searches all labels within the same object kind and
referential, selecting the union of five nearest neighbors per label. It no
longer uses alphabetically adjacent overlapping windows or a cosine acceptance
threshold. Matrix work runs off the event loop in bounded row blocks.
Native OpenAI Decisions, resolved through mini, classifies candidate pairs as
duplicate, distinct, or insufficient_context using their labels, type and
available descriptions. The profile must support Decisions; no provider or
model substitution is performed. Calls contain at most 64 pair questions and
only the evidence needed for that batch. Every internal pair of a semantic
group must be confirmed; overlapping groups are never unioned transitively.
Exact-label buckets remain deterministic and are expanded after confirmation.
Selected IDs still prefer the highest association count, with ID tie-breaking.
semanticCoverage=scoped_top_k_with_decisions and semanticNeighbors=5 describe
the coverage. Complete means every selected candidate was evaluated, not that
all possible catalogue pairs were judged. Embedding or decision failures mark
the affected kind unavailable and the response partial; deterministic exact
findings remain available. Cancellation propagates. Within-job fuzzy checks
retain their existing CPU guard and explicit unavailable status.
Rules and tests¶
Definitions and prompt instructions live in referential_policy.py;
referential_analysis.py and referential_duplicates.py evaluate them.
Tests below are in tests/lexi/services.
| Rules | Evaluation / generation | Regression evidence |
|---|---|---|
| Missing family; family size 3–30 | Jobs; family suggestions include populations | test_referential_analysis: family bounds 2/3/30/31 |
| Missing or fewer than 3 missions, complete target 5 | Jobs; mission suggestions count raw paragraphs/lists centrally | Analysis mission parsing and complete/extend tests; existing test_job_missions |
| Duplicate job titles, exact and semantic | Scope-aware duplicate groups, human merge only | Analysis duplicate tests |
| Skill names over 5 words, missing descriptions | Skills; catalogue, expansion, assignment, descriptions, repair | Analysis 5/6-word and missing-description tests |
| Exact/semantic skill duplicates; within-job fuzzy duplicates at 0.80 | Canonical selection and targeted repair | Analysis exclusions and duplicate tests; generation tests |
| DGI objective 10% | Existing available DGI metric; relevant capabilities only | Analysis DGI tests |
| Fewer than 10 skills, target deviation over ±30% | Job–Skills; final quantity selection | Analysis tolerance tests; parity vectors |
| Unique-skill/job ratio 2–4 | Global granularity; indicative range, repair consolidates or specializes with the shared catalogue | Analysis granularity curve; parity vectors; generation granularity tests |
| Over 50% linked to fewer than 3 or at least 15 jobs | Transversality; genuine reuse only | Analysis 2/3/14/15 tests; parity vectors |
| Uniform levels including zero/one skill | Job–Skills; independent level judgment | Analysis and parity tests |
| Orphan skills | Job–Skills; new skills must be associated; a replacement removes the skills it orphaned | Analysis large-scope test; generation projection and replacement tests |
| Client quantity, groups, hard/soft, levels, locale and wording | Existing parameters plus shared instructions at relevant stages | Generation quota/scope/level tests; existing Lexi suites |
The 40 frozen HRX vectors in test_referential_parity.py cover historical scores,
action lists, mixed targets, validation exceptions and ordering. Do not collapse
the G/J/Q hook score into the separately displayed 50/25/25 score. Jobs retain
60/40 coverage/size weighting; Skills retain 50/50 DGI/LONG weighting when a DGI
driver is available. Without one, LONG alone scores a non-empty catalogue and
decides whether its scores are satisfactory; an empty catalogue keeps its
neutral 50. LONG is maximal up to 5% long labels and zero at 20%. Score
rounding follows JavaScript.
Policy metadata includes priorities and the two historical color scales.
Versioned generation¶
Add policy_version, quality_source and skill_group_types to generated-skills
requests. Inline quality_context remains supported within the existing request
budget. For partial regeneration the source includes selected jobs, all reusable
skills, total job population and usage counters for unselected jobs; it excludes
unselected job descriptions and missions. resultsNumber is the real
final target. The selected job IDs must be unique and belong to the snapshot.
Imported catalogues keep their separate provided-skills contract.
Catalogue creation/expansion/assignment, description generation and proficiency inference receive the shared policy. AIHub selects canonical final skills and hard/soft quotas, evaluates, optionally performs one targeted repair and re-evaluates the selection. An invalid repair is discarded; technical failures use the workflow's existing error callback.
The repair prompt requires existing proficiency levels to be preserved unless a level is missing, outside the allowed scale, or contradicted by explicit evidence in the supplied job context. Uniform levels alone do not justify a change, even when a uniform-level warning remains. Duplicate cleanup, skill counts, group quotas and other unrelated findings do not justify changing a valid level.
When the unique-skill/job ratio is outside 2–4, every repair batch also receives the ratio and the 200 most reused skills of the projected referential, within 40,000 characters. A too-high ratio may reuse a shared skill only when it covers the same or a broader capability; a too-low ratio may specialize an overly generic skill. Batches run sequentially on the latest accepted selection. A batch is kept only if it increases neither the number of findings nor the distance of the ratio from the desired range. The completion log reports the ratio before and after repair, without business content.
A replacement (generation_mode replace) is evaluated as HRX persists it:
referential skills detached from every job by the replacement are removed from
the projection, while skills still used by unselected jobs remain. HRX also
keeps an orphan referenced by a validation proposal; the persisted analysis is
authoritative in that case. Statistical targets never justify
invented missions, arbitrary levels or irrelevant associations.
Partial regeneration preserves unselected associations and stored shared skill
metadata. Job identifiers disambiguate homonymous job titles. The success
callback includes policy_version and quality_report with remaining issues,
semantic findings and completeness. HRX must persist this selection without a
second quota calculation. Versionless requests and already-running callbacks
retain historical processing.
Family and mission suggestions remain proposals. Skills generation never rewrites imported job families or missions, merges jobs, or restructures families. Those findings can legitimately remain after skills generation.
Delivery and verification¶
Deploy AIHub before HRX backend, then HRX frontend. No database migration is required. Use synthetic data for validation. New analysis/repair logs contain technical identifiers, exception types and counts, never referential content. HRX disables generation debug. API schema examples are exposed in the generated Lexi HTTP reference.
Bounded transfers without a business volume quota¶
The generated-skills and referential-analysis workflows do not impose a total job, skill or association count limit. They retain normal per-request safety budgets (50,000 JSON nodes, 2,000,000 total text characters, 200,000 per field, depth 20). Private HRX transfers split input and output into structural fragments of at most 256,000 bytes and fewer than 30,000 nodes per page. Oversized individual records fail explicitly; content is never silently truncated.
A QualityReference contains organization, referential and execution UUIDs, never
a caller-selected URL. AIHub uses LEXI_HRX_FUNCTIONS_ORIGIN and
LEXI_SKILLS_GENERATION_COMPLETE_API_KEY to call HRX's lexi-quality-transfer.
HRX recognizes the existing callback secret and stores pages in the existing
private lexi-skill-catalogs bucket. Users can read status and results only after
JWT verification and active organization-membership checks. Input pages are
removed at completion/failure; result pages remain private in HRX.
Analysis acknowledges with status=pending and its source reference. A background
worker loads every page, validates the graph, evaluates it, uploads every result
page, then publishes completion. Deterministic and semantic analyses use separate
pools (two each per process by default) so a fast deterministic check never waits
behind semantic work. One transfer shares a keep-alive connection pool and exchanges
up to eight pages at once (LEXI_QUALITY_TRANSFER_CONCURRENCY); input pages are
applied in order and completion is published only after every result page is
stored.
Generation similarly hydrates the source after acknowledgment. Failures use an
explicit failed state or the existing generation failure callback. This uses the
existing in-process background lifecycle, not a durable distributed queue; process
restarts require restarting interrupted work. An owned heartbeat every 30 seconds
lets HRX report a missing worker after two minutes without imposing a total
analysis-duration deadline. The signal remains active until result uploads finish; its separate storage object
cannot overwrite completion. HRX loading and AIHub assembly still
consume memory, so absence of an entity quota does not imply infinite capacity.
Generation prompts receive at most 200 relevant reusable skill summaries within 40,000 characters. The full catalogue remains available to deterministic checks. Role batches contain at most 40 jobs; the single repair pass uses at most 10 jobs per call. Text-heavy inputs reduce these sizes further. Each job is considered at most once in the repair pass; there is no recursive repair loop. Provider context limits and individual-record safety limits still apply.
The stored referential's quantity, level scale and hard/soft settings govern an existing referential. HRX pre-fills the wizard and preserves these settings. Jobs without usable generation preserve their previous associations; all-empty output fails. A null definition remains an explicit missing-description finding. Missing levels receive one repair attempt and are rejected if still invalid. A DGI driver computed before catalogue expansion is marked unavailable in the quality report until refreshed; it cannot certify new skills.
Synthetic tests cover 48,000 associations, 100,000 small JSON values, more than
10,000 semantic labels, private source scope checks, failed transfers and a
25-job repair split into three batches. The HRX coverage matrix is maintained in
docs/lexi/NB-9113-regles-communes.md in the HRX repository.