hired.alignment#

JD-vs-candidate alignment: classify each requirement honestly into four buckets.

Public surface:

The intelligence (judging transfer distance, trainability, evidence) is supplied by the hired-align skill (Claude as brain) or an injected LLM; this package provides the schemas, deterministic scoring, and rendering. See misc/docs/DESIGN.md §6-8.

Functions

classify(record)

Fill gap_size and bucket (and needs_clarification) in place.

assign_bucket(record)

Assign the alignment bucket for a record, or None if it should be a clarifying question instead.

apply_ai_leverage(closeability, ai_leverage, ...)

Soften a codified gap's closeability by the candidate's AI leverage.

compute_gap_size(required_level, candidate_level)

Residual gap, floored at zero.

rank_clarifications(records, *[, ...])

Produce clarifying questions for askable records, highest info-gain first.

is_decision_stable(records)

True when no remaining open unknown could flip the verdict.

should_ask(record)

Whether to route this record to a clarifying question.

info_gain(record)

Expected information gain of resolving this requirement, wrt the verdict.

render_report_markdown(report)

Render the report as a Markdown string.

diff_reports(old, new)

Return a structured diff of two alignment-report dicts.

summarize_diff(diff)

A short human-readable summary of diff_reports() output.

Classes

Requirement(**data)

One atomic requirement extracted verbatim from a job description.

RequirementRecord(**data)

The analysis of one requirement against the candidate's knowledge.

Evidence(**data)

A verbatim grounding span for a match judgment.

AlignmentReport(**data)

A complete, verdict-first alignment analysis for one JD.

Verdict(**data)

ScoreSummary(**data)

NextAction(**data)

Clarification(**data)

A question to ask the candidate to resolve a decision-relevant unknown.

InterviewPrep(**data)

Bucket(*values)

The four alignment buckets.

MatchType(*values)

How the candidate's background relates to the requirement (Axis A).

RequirementClass(*values)

How decision-critical a requirement is.

SkillType(*values)

Closeability(*values)

How hard a gap is to close (Axis B), after the AI-leverage modifier.

CloseMethod(*values)

TimeToClose(*values)

Transferability(*values)

AILeverage(*values)

How much the candidate's standing AI-agent capability lowers the ramp.

FieldCompleteness(*values)

Local closed-world flag: may a missing value be read as a real negative?

Recommendation(*values)

FitBand(*values)

class hired.alignment.AILeverage(*values)[source]#

Bases: str, Enum

How much the candidate’s standing AI-agent capability lowers the ramp.

Applies to codified / knowledge-breadth gaps, not tacit-judgment or enduring-aptitude gaps (those it cannot rescue).

class hired.alignment.AlignmentReport(**data)[source]#

Bases: BaseModel

A complete, verdict-first alignment analysis for one JD.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.Bucket(*values)[source]#

Bases: str, Enum

The four alignment buckets.

class hired.alignment.Clarification(**data)[source]#

Bases: BaseModel

A question to ask the candidate to resolve a decision-relevant unknown.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.CloseMethod(*values)[source]#

Bases: str, Enum

class hired.alignment.Closeability(*values)[source]#

Bases: str, Enum

How hard a gap is to close (Axis B), after the AI-leverage modifier.

class hired.alignment.Evidence(**data)[source]#

Bases: BaseModel

A verbatim grounding span for a match judgment.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.FieldCompleteness(*values)[source]#

Bases: str, Enum

Local closed-world flag: may a missing value be read as a real negative?

class hired.alignment.FitBand(*values)[source]#

Bases: str, Enum

class hired.alignment.InterviewPrep(**data)[source]#

Bases: BaseModel

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.MatchType(*values)[source]#

Bases: str, Enum

How the candidate’s background relates to the requirement (Axis A).

class hired.alignment.NextAction(**data)[source]#

Bases: BaseModel

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.Recommendation(*values)[source]#

Bases: str, Enum

class hired.alignment.Requirement(**data)[source]#

Bases: BaseModel

One atomic requirement extracted verbatim from a job description.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.RequirementClass(*values)[source]#

Bases: str, Enum

How decision-critical a requirement is.

class hired.alignment.RequirementRecord(**data)[source]#

Bases: BaseModel

The analysis of one requirement against the candidate’s knowledge.

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.ScoreSummary(**data)[source]#

Bases: BaseModel

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class hired.alignment.SkillType(*values)[source]#

Bases: str, Enum

class hired.alignment.TimeToClose(*values)[source]#

Bases: str, Enum

class hired.alignment.Transferability(*values)[source]#

Bases: str, Enum

class hired.alignment.Verdict(**data)[source]#

Bases: BaseModel

model_config: ClassVar[ConfigDict] = {}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

hired.alignment.apply_ai_leverage(closeability, ai_leverage, *, skill_type, is_tacit=False)[source]#

Soften a codified gap’s closeability by the candidate’s AI leverage.

Tacit/soft gaps and structurally-hard gaps are never softened — AI agents extend breadth of codified knowledge, not judgment or enduring aptitude.

Return type:

Closeability

>>> apply_ai_leverage(Closeability.REQUIRES_EXPERIENCE, AILeverage.HIGH,
...                    skill_type=SkillType.TECHNICAL)
<Closeability.LEARNABLE: 'learnable'>
>>> apply_ai_leverage(Closeability.REQUIRES_EXPERIENCE, AILeverage.HIGH,
...                    skill_type=SkillType.SOFT_SKILL)
<Closeability.REQUIRES_EXPERIENCE: 'requires_experience'>
hired.alignment.assign_bucket(record)[source]#

Assign the alignment bucket for a record, or None if it should be a clarifying question instead.

Returns None when the requirement is UNKNOWN on an OPEN field — that routes to elicitation rather than being scored as a gap (the “don’t assume absence” rule). UNKNOWN on a CLOSED field is treated as a real gap.

Return type:

Bucket | None

hired.alignment.classify(record)[source]#

Fill gap_size and bucket (and needs_clarification) in place.

Returns the same record for convenience.

Return type:

RequirementRecord

hired.alignment.compute_gap_size(required_level, candidate_level)[source]#

Residual gap, floored at zero.

Return type:

int

hired.alignment.diff_reports(old, new)[source]#

Return a structured diff of two alignment-report dicts.

Both inputs are AlignmentReport.model_dump() dicts. The result has:

  • verdict_changed / verdict_old / verdict_new

  • fit_old / fit_new

  • bucket_changes: list of {requirement, from, to} for requirements whose bucket moved (the heart of a refresh — typically UNKNOWN→known as Q&A resolves false negatives)

  • added / removed: requirement texts present in only one version

  • clarifications_resolved: clarifying questions in old but not new

Return type:

dict[str, Any]

hired.alignment.info_gain(record)[source]#

Expected information gain of resolving this requirement, wrt the verdict.

Heuristic: uncertainty × criticality. An impact override (1-5) scales criticality when the analyst has a sharper view than the requirement class.

Return type:

float

hired.alignment.is_decision_stable(records)[source]#

True when no remaining open unknown could flip the verdict.

Concretely: there are no askable (decision-relevant, open, unknown) requirements left. This is the sharpest stop criterion from the research.

Return type:

bool

hired.alignment.rank_clarifications(records, *, max_questions=None, min_info_gain=0.0)[source]#

Produce clarifying questions for askable records, highest info-gain first.

The question text is left to the analyst; this returns the prioritized skeleton (requirement, reason, info_gain) so the caller can fill question.

Return type:

list[Clarification]

hired.alignment.render_report_markdown(report)[source]#

Render the report as a Markdown string.

Return type:

str

hired.alignment.should_ask(record)[source]#

Whether to route this record to a clarifying question.

Ask only when it’s UNKNOWN on an OPEN field and decision-relevant — the “don’t assume absence from silence” rule. CONTRADICTED facts and closed-field unknowns are real gaps, not questions.

Return type:

bool

hired.alignment.summarize_diff(diff)[source]#

A short human-readable summary of diff_reports() output.

Return type:

str

Modules

base

Schemas for JD-vs-candidate alignment analysis.

diff

Deterministic diff between two alignment reports.

elicitation

The honesty loop: rank unknowns into the most informative questions first.

report

Render an AlignmentReport to Markdown.

rubric

Deterministic bucket assignment — the two-axis rubric in code.