# Core HR Policy QA MVP

This is a small static MVP for the Applied AI Engineer policy-QA screen.

## What it does

- Generates a toy HR corpus under `docs/`: leave and time off, expenses and travel, remote work and equipment, one employee handoff, and one privileged HR operations addendum.
- Exposes a browser/Node retrieval tool in `agent.js`: `PolicyAgent.retrievePolicyDocuments(question, employee)`.
- Answers common employee policy questions with deterministic synthesis over retrieved chunks, then returns a plain text answer with citations.
- Attaches policy owner, document version, and effective-date metadata to every citation.
- Enforces employee jurisdiction before retrieval, so California, New York, and Texas addenda cannot be retrieved or cited for the wrong employee jurisdiction.
- Hosts as static GitHub Pages content at `/policy-agent/`.

## Key decisions

I kept the first version static and deterministic because the screen is about the retrieval and grounding shape, not model quality. That makes every answer auditable: the answer function can only cite chunks in the generated corpus.

The corpus has document types that mirror the prompt: general policy docs, an employee handoff that supplies employee-specific facts, and privileged HR guidance that is available to retrieval but downranked unless the question involves exceptions, accommodations, or escalation.

The retrieval tool is intentionally simple: token expansion, intent-specific boosts, and chunk scoring. With more time, I would replace this with embeddings plus a policy-aware reranker, keep citations tied to paragraph-level chunks, and add an LLM answer step that is constrained to retrieved evidence.

I made versioning first-class even in the static demo. Each indexed chunk inherits metadata from `documentRegistry`: owner, version, effective start, optional effective end, and precedence. Retrieval filters to policies effective on the answer's `asOfDate`.

I also made jurisdiction access control explicit. General US-wide documents are available to everyone, privileged HR guidance is globally available to the internal assistant, and jurisdiction addenda are available only when the employee's HR work location matches the addendum. This is enforced in `canAccessChunk`, used by both retrieval and fallback citation lookup. The UI shows gated-out documents, but they are not eligible evidence.

## Test prompts

- How many vacation days do I get per year?
- I've been here eight months and I'm part-time - am I eligible for parental leave?
- Can I expense a business-class flight?
- Is a gym membership reimbursable?
- I work 19 hours per week. Am I eligible for parental leave?
- Can my manager approve a business-class flight?
- I need business class for a medical accommodation. Can I book it?
- What does the New York leave addendum say about parental leave?

## Edge cases to discuss

- Event date versus question date: a reimbursement answer should use the booking/submission date, while leave eligibility may use birth/adoption date and requested leave start date.
- Exact thresholds: 6 months of service, 20 scheduled hours, 90 days for wellness stipend, 60-day retroactive claims, and 8-hour one-way flight time.
- Employee facts versus policy: HRIS/handoff facts should be timestamped and should not override policy.
- Conflicting documents: use domain owner and precedence, surface the conflict, and escalate when required.
- Privileged guidance: retrieve it for internal support workflows, but cite it only for accommodations, legal escalation, exceptions, or conflicts.
- Local/state overlays: explain company policy and route protected-leave questions to People Operations instead of pretending the company doc is complete law.
- Jurisdiction mismatch: if a California employee asks about New York policy, the system should say the New York addendum is gated out and answer only from US-wide plus California documents.

## Embedding design

This static demo does not call an embedding model. It uses token scoring so the whole thing can run on GitHub Pages. The production shape would be:

1. Ingest each policy document into stable paragraph/section chunks.
2. Store chunk text plus metadata: `doc_id`, `chunk_id`, `version`, `effective_from`, `effective_to`, `owner`, `visibility`, `applicable_jurisdictions`, and `supersedes`.
3. Create an embedding for the chunk text, and optionally a separate embedding for title/section headings.
4. At query time, derive employee context from HRIS: jurisdiction, role, employment type, scheduled hours, tenure, and permissions.
5. Apply metadata filters before vector search: effective date, visibility, employee permission, and jurisdiction.
6. Run vector search only over accessible chunks.
7. Rerank the accessible candidates with policy-aware features: exact threshold terms, policy owner, jurisdiction specificity, version recency, and section type.
8. Pass only those retrieved chunks to the answer model, requiring citations by `chunk_id`.

The key point is that embeddings do not replace access control. The vector index should support metadata prefilters, and the application layer should re-check access before citation and answer generation.

## Versioning approach

- Store immutable policy versions with `doc_id`, `version`, `effective_from`, `effective_to`, `owner`, `visibility`, and `supersedes`.
- Chunk by stable section IDs rather than line numbers so citations survive document edits.
- At answer time, choose the policy version active on the relevant event date, not necessarily the latest version.
- Keep superseded chunks queryable for audits and historical employee questions.
- Run regression evals whenever a policy document changes: common prompts, threshold prompts, conflict prompts, and access-control prompts.

## Next steps

- Add role and location-specific policy precedence.
- Add access-control tests for privileged docs.
- Add answer evals for citation precision, refusal behavior, and conflicting-doc handling.
- Use a real vector index and a small answer model with strict cited-evidence prompting.
