Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
81982e8
test(job-analysis): define qualification-rule review package
seonghobae Aug 23, 2026
20f05a0
test(job-analysis): expose qualification-rule review contract
seonghobae Aug 23, 2026
5548912
test(job-analysis): add governed qualification-rule regressions
seonghobae Aug 23, 2026
89e83eb
test(job-analysis): gate qualification-rule review artifact
seonghobae Aug 23, 2026
491f5f8
docs(job-analysis): define qualification-rule review boundary
seonghobae Aug 23, 2026
85883b6
docs(job-analysis): record qualification-rule review slice
seonghobae Aug 23, 2026
8e1358f
docs(job-analysis): add qualification-rule review ADR
seonghobae Aug 23, 2026
2490464
docs(job-analysis): record qualification-rule primary sources
seonghobae Aug 23, 2026
f064980
docs(job-analysis): trace qualification-rule governance
seonghobae Aug 23, 2026
f48c23e
feat(job-analysis): implement governed qualification-rule review
seonghobae Aug 23, 2026
4c42b42
docs(job-analysis): use current Uniform Guidelines source
seonghobae Aug 23, 2026
d92ac4c
test(job-analysis): cover malformed namespaced rule references
seonghobae Aug 23, 2026
79adb79
fix(job-qualification-rule-review): make trust-boundary validation no…
seonghobae Aug 25, 2026
14eab4e
test(job-analysis): make qualification hardening regressions determin…
seonghobae Aug 25, 2026
5bc1663
fix(job-analysis): consolidate qualification review quality lane
seonghobae Sep 6, 2026
fde420a
docs(job-analysis): align qualification review traceability with prot…
seonghobae Sep 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/foundation-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,54 @@ jobs:
run: npm run validate
- name: Prove Foundation CI dependency hygiene
run: bash tests/test_foundation_ci_dependency_hygiene.sh
- name: Set up exact Job Qualification Rule Review Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14.7"
check-latest: false
- name: Install reviewed test toolchain
run: |
python -m pip install --require-hashes --no-deps --only-binary=:all: -r .github/requirements/foundation-test.txt
python -m pip check
- name: Run Job qualification rule review installed-artifact contract
run: |
printf '%s\n' 'setuptools==84.0.0 --hash=sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670' > /tmp/orgmetra-job-qualification-rule-review-build.txt
python -m pip install --require-hashes --no-deps --only-binary=:all: -r /tmp/orgmetra-job-qualification-rule-review-build.txt
rm -rf /tmp/orgmetra-job-qualification-rule-review-build-tree /tmp/orgmetra-job-qualification-rule-review-dist /tmp/orgmetra-job-qualification-rule-review-venv
cp -a packages/job-qualification-rule-review /tmp/orgmetra-job-qualification-rule-review-build-tree
mkdir -p /tmp/orgmetra-job-qualification-rule-review-dist
python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-job-qualification-rule-review-dist /tmp/orgmetra-job-qualification-rule-review-build-tree
test "$(find /tmp/orgmetra-job-qualification-rule-review-dist -maxdepth 1 -type f -name '*.whl' | wc -l)" -eq 1
python -m venv /tmp/orgmetra-job-qualification-rule-review-venv
/tmp/orgmetra-job-qualification-rule-review-venv/bin/python -m pip install --require-hashes --no-deps --only-binary=:all: -r "$GITHUB_WORKSPACE/.github/requirements/foundation-test.txt"
wheel_path="$(find /tmp/orgmetra-job-qualification-rule-review-dist -maxdepth 1 -type f -name '*.whl' -print -quit)"
wheel_sha="$(sha256sum "$wheel_path" | awk '{print $1}')"
printf 'orgmetra-job-qualification-rule-review[test] @ file://%s --hash=sha256:%s\n' "$wheel_path" "$wheel_sha" > /tmp/orgmetra-job-qualification-rule-review-install.txt
/tmp/orgmetra-job-qualification-rule-review-venv/bin/python -m pip install --require-hashes --no-deps -r /tmp/orgmetra-job-qualification-rule-review-install.txt
/tmp/orgmetra-job-qualification-rule-review-venv/bin/python -m pip check
/tmp/orgmetra-job-qualification-rule-review-venv/bin/python - <<'PY'
from importlib.metadata import metadata
from pathlib import Path
import coverage
import pytest
import pytest_cov
import orgmetra_job_qualification_rule_review

venv_root = Path("/tmp/orgmetra-job-qualification-rule-review-venv").resolve()
module_path = Path(orgmetra_job_qualification_rule_review.__file__).resolve()
if not module_path.is_relative_to(venv_root):
raise SystemExit(f"package imported outside isolated environment: {module_path}")
for module in (coverage, pytest, pytest_cov):
dependency_path = Path(module.__file__).resolve()
if not dependency_path.is_relative_to(venv_root):
raise SystemExit(
f"test dependency imported outside isolated environment: {dependency_path}"
)
if "test" not in (metadata("orgmetra-job-qualification-rule-review").get_all("Provides-Extra") or []):
raise SystemExit("built distribution does not expose the reviewed test extra")
PY
cd /tmp
COVERAGE_FILE=/tmp/orgmetra-job-qualification-rule-review.coverage /tmp/orgmetra-job-qualification-rule-review-venv/bin/python -m pytest -c "$GITHUB_WORKSPACE/packages/job-qualification-rule-review/pyproject.toml" "$GITHUB_WORKSPACE/packages/job-qualification-rule-review/tests"
- name: Run owned unit and service contracts once
run: |
PYTHONPATH=packages/candidate-evidence/src COVERAGE_FILE=/tmp/orgmetra-candidate-evidence.coverage python -m pytest -c packages/candidate-evidence/pyproject.toml packages/candidate-evidence/tests
Expand Down
33 changes: 33 additions & 0 deletions docs/adr/0104-governed-job-qualification-rule-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ADR 0104: Governed Job qualification-rule review

- Status: proposed on active PR; not protected-main truth until merged.
- Date: 2026-08-24

## Context

Protected `develop` models Job Analysis versions, Tasks, FJA and KSAO evidence, and the PRD requires qualification rules, but there is no bounded governance object proving which job-analysis evidence supported a proposed qualification rule before that rule can influence recruiting or selection.

OPM describes job analysis as the systematic linkage of job tasks and competencies/KSAs and states that job-analysis information supports recruitment, qualification, assessment and selection. OPM also emphasizes evidence for task/KSA importance and current job requirements. The Uniform Guidelines on Employee Selection Procedures provide a federal framework for the proper use and documentation of selection procedures. Orgmetra uses these public sources as design evidence only; this package does not decide legal compliance, reproduce licensed standards, or validate a selection procedure.

## Decision

Create an Orgmetra-owned `JobQualificationRuleReviewPacket` as PII-minimized, human-reviewed proposal evidence.

The packet binds tenant and authoritative Job scope, one Job Analysis snapshot reference/digest, one opaque qualification-rule artifact reference/digest, Task/KSAO/source linkage digests, a controlled rule category, a business-effective date, distinct requester/reviewer correlations, a controlled review reason, bounded evidence version, human review time, and an Orgmetra-generated system-recorded UTC issuance time.

The controlled category describes only the type of job requirement evidence (`credential_requirement`, `education_training_requirement`, `experience_requirement`, `knowledge_skill_ability_requirement`, or `task_or_work_requirement`). It does not record candidate qualification, cut scores, assessment outcomes, legal status, or an autonomous eligibility decision.

Every packet is fixed to human review and `not_authorized_for_candidate_or_employment_decision`. Before a reviewed rule changes authoritative Job/Job Analysis truth or is used in recruiting/selection, the host must re-resolve exact tenant/Job/snapshot/artifact/linkage evidence and reviewer authority at the relevant business-time coordinate and atomically preserve immutable audit/outbox evidence.

## Privacy and integrity consequences

Canonical evidence excludes Person/candidate identifiers and PII, compensation, assessment scores, raw rule or qualification text, credentials, prompts/model output, and free-form review text. Operational HRIS references use the core non-sentinel UUID contract; packet-owned artifact and actor correlations require opaque UUIDv4 references.

Trust-bearing primitives are exact built-in types. Malformed/noncanonical IDs or SHA-256, unreviewed categories/reasons, actor overlap, invalid evidence versions, caller-supplied system time, future review time, mutable fixed governance, and post-issuance mutation fail closed. The process-local issuance registry is defense in depth only; durable identity, uniqueness, authorization, and audit remain host responsibilities.

## Alternatives rejected

- **Store free-form minimum-qualification text in the governance packet.** Rejected because it expands durable sensitive/business text without improving provenance; the reviewed artifact is referenced and hashed instead.
- **Evaluate candidates inside this packet.** Rejected because job-rule governance and candidate evidence/selection decisions are distinct high-impact boundaries.
- **Infer rules directly from an LLM.** Rejected because model output is untrusted draft evidence and cannot substitute for Job Analysis linkage or accountable human review.
- **Treat a qualification category as proof of validity or legality.** Rejected because jurisdiction, job relatedness, validity and applicant application require separate authoritative review.
29 changes: 29 additions & 0 deletions docs/doctoring/job-qualification-rule-review-references.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Job qualification-rule review references

Reviewed: 2026-08-24.

## Authoritative public sources

U.S. Office of Personnel Management. (n.d.). *Job analysis*. https://www.opm.gov/frequently-asked-questions/assessment-policy-faq/job-analysis/

- OPM describes job analysis as a systematic procedure for identifying work tasks and the competencies/KSAs directly related to performance.
- OPM states that job-analysis information supports recruitment, assessment, selection, performance management, and career development, and that evidence should establish the importance of tasks and KSAs.

U.S. Office of Personnel Management. (n.d.). *General Schedule qualification policies*. https://www.opm.gov/policy-data-oversight/classification-qualifications/general-schedule-qualification-policies/

- OPM distinguishes job-analysis evidence from the ways applicants may demonstrate KSAs, including qualifying experience, education, or training.
- Orgmetra uses that distinction only to keep Job qualification-rule provenance separate from candidate evaluation; it does not adopt federal qualification standards as a universal employer policy.

Equal Employment Opportunity Commission, Department of Justice, Department of Labor, & Civil Service Commission. (1978). *Uniform Guidelines on Employee Selection Procedures*, 29 C.F.R. pt. 1607. https://www.ecfr.gov/current/title-29/subtitle-B/chapter-XIV/part-1607

- The eCFR current-title URL is the authoritative continuously updated regulatory publication target. Automated access was rate-limited during the 2026-08-24 review, so the regulation text was cross-checked against the official GovInfo annual CFR publication at https://www.govinfo.gov/content/pkg/CFR-2023-title29-vol4/pdf/CFR-2023-title29-vol4-part1607.pdf rather than treating the older annual edition as current law.
- The Guidelines provide a federal framework for proper use, validity evidence, and documentation of employee selection procedures.
- This package records review provenance only. It makes no finding that a qualification rule is legally required, job-related, validated, nondiscriminatory, or appropriate for a particular jurisdiction or applicant.

## Repository sources of truth

ContextualWisdomLab. (2026). *Orgmetra product requirements document*. `docs/PRD.md` on protected `develop`.

ContextualWisdomLab. (2026). *Orgmetra Job Analysis kernel*. `packages/hris-kernel/src/orgmetra_hris_kernel/job_analysis.py` on protected `develop`.

The protected-main sources remain authoritative for Job/Job Analysis ownership. This active PR adds review evidence only and does not create a second source of Job truth or a candidate-screening engine.
29 changes: 29 additions & 0 deletions docs/traceability/job-qualification-rule-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Job qualification-rule review traceability

## State boundary

- **Protected-parent adoption snapshot:** `develop@eb9757f8649aaad026a9865508d9aad50c1a7a4f` includes protected #161's repository-quality consolidation and remains the parent adopted by this Draft lane. The protected branch must be re-read again before merge; this snapshot is evidence of the adoption point, not a perpetual claim about the latest protected head.
- **Active PR truth:** this Draft branch proposes `JobQualificationRuleReviewPacket`; it is not protected-main truth until normal protected integration completes.
- **Foreign dependencies:** none are written or queried directly. This slice is Orgmetra-owned and standalone.

## Requirement-to-evidence matrix

| Requirement | Production boundary | Regression / gate |
|---|---|---|
| Tie proposed qualification rules to authoritative Job Analysis | Job + Job Analysis snapshot reference/digest | scope-ID and digest regressions |
| Preserve Task/KSAO/source provenance | independent Task, KSAO and source SHA-256 digests | malformed digest regressions |
| Avoid free-form sensitive rule storage | opaque qualification-rule artifact reference + digest and closed rule category | canonical privacy assertions |
| Keep job-rule design separate from candidate evaluation | fixed `not_authorized_for_candidate_or_employment_decision` | fixed-governance direct-construction tests |
| Preserve authoritative identifier ownership | tenant/Job/snapshot use non-sentinel operational UUIDs; packet-owned artifact/actors use UUIDv4 | namespace/sentinel/version regressions |
| Preserve business, review and system-recorded time separately | exact `effective_on`, exact UTC `reviewed_at`, owner-generated UTC `recorded_at` | type/timezone/future-review/caller-injection regressions |
| Require accountable human review | distinct requester/reviewer UUIDv4 correlations and mandatory review state | actor-overlap and governance regressions |
| Version high-impact evidence | bounded exact integer `evidence_version` | bool/non-int/range and digest-change regressions |
| Detect in-process post-issuance mutation | process-local weak issuance digest outside packet slots; export revalidates one snapshot | valid-field and hostile-runtime mutation regressions |
| Preserve exact package/artifact evidence | canonical Foundation CI builds and SHA-256-binds the isolated wheel after leaf-workflow retirement | Foundation installed-artifact contract + leaf-reintroduction regression |
| Preserve exact owned test sufficiency | package pytest config requires statement and branch coverage 100% | `--cov-fail-under=100`, branch coverage enabled |

## Authoritative next action

Before a reviewed rule may alter Job/Job Analysis truth or influence applicant screening or selection, the Orgmetra host must re-resolve the exact tenant, Job, Job Analysis snapshot, qualification-rule artifact, Task/KSAO/source evidence, reviewer identity and authority, and current business-time context. Any authoritative change must preserve human confirmation and immutable audit/outbox evidence atomically.

The packet does not decide whether an applicant satisfies a rule, whether a rule is lawful or validated, or whether any employment action should occur. LLM output remains untrusted draft evidence only.
8 changes: 4 additions & 4 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"files": [
{
"path": ".github/workflows/foundation-ci.yml",
"sha256": "b6a4365936b66803a8112f034c77d53d33301a7a798ed4f68746a4f2d8b081d7",
"bytes": 6651,
"lines": 125
"sha256": "2e7e89e7c1158b23e4cf5947ab2a6440c3a3dc47f4a6b23182ff5a15e53b5eaf",
"bytes": 10324,
"lines": 169
},
{
"path": ".gitignore",
Expand Down Expand Up @@ -472,4 +472,4 @@
"lines": 637
}
]
}
}
9 changes: 9 additions & 0 deletions packages/job-qualification-rule-review/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## 0.1.0 - 2026-08-24

- Add governed Job qualification-rule review evidence linked to authoritative Job Analysis.
- Bind Task, KSAO, source, snapshot, and qualification-rule artifact provenance by SHA-256 without copying candidate PII or raw rule text.
- Keep rule proposals explicitly non-authoritative for applicant screening, candidate rejection, and employment decisions.
- Require distinct requester/reviewer correlations, controlled rule categories/reasons, explicit evidence versioning, business-effective time, human-review time, and owner-generated system-recorded time.
- Add deterministic canonical JSON/SHA-256 correlation, redacted representations, process-local post-issuance tamper detection, hostile runtime-type regressions, hash-bound isolated-wheel execution, and exact 100% owned statement/branch coverage.
30 changes: 30 additions & 0 deletions packages/job-qualification-rule-review/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Orgmetra Job qualification-rule review

This package creates **human-reviewed, evidence-linked Job qualification-rule proposals**. It does not screen a candidate, reject an applicant, assign a qualification outcome, or mutate authoritative Job or Job Analysis state.

A packet binds one tenant and Job to an exact Job Analysis snapshot, an opaque reviewed qualification-rule artifact, explicit Task/KSAO/source evidence digests, one controlled rule category, a business-effective date, distinct requester/reviewer correlations, evidence version, human review time, and an Orgmetra-generated system-recorded issuance time.

The canonical evidence deliberately excludes candidate/person identifiers, names, email addresses, phone numbers, salary, assessment scores, cut scores, raw qualification/rule text, prompts, model output, credentials, and free-form review text. The reviewed artifact content remains outside this evidence envelope and is correlated by opaque reference plus SHA-256 digest.

## Controlled categories

- `credential_requirement`
- `education_training_requirement`
- `experience_requirement`
- `knowledge_skill_ability_requirement`
- `task_or_work_requirement`

These categories classify the *kind of reviewed job requirement evidence*. They do not establish that a particular qualification standard is lawful, necessary, validated, or satisfied by any person.

## Safety boundary

Every packet remains fixed to:

- purpose `job_qualification_rule_review`;
- review state `reviewed_for_authoritative_resolution`;
- decision authority `not_authorized_for_candidate_or_employment_decision`;
- mandatory human review.

Before any qualification rule affects recruiting or selection, the Orgmetra host must re-resolve tenant, Job, Job Analysis snapshot, exact artifact and linkage digests, accountable reviewer identity/authority, and the current business-time context. It must then persist authoritative changes with immutable audit/outbox evidence. Candidate evaluation is a separate governed boundary.

System-recorded time is generated by this package rather than supplied by callers. Trust-bearing scalar values require exact runtime primitives. Canonical exports revalidate a single payload snapshot and compare it with an issuance digest held outside writable packet slots so post-issuance mutation fails closed. This process-local seal is defense in depth, not a durable signature or authorization mechanism.
24 changes: 24 additions & 0 deletions packages/job-qualification-rule-review/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[build-system]
requires = ["setuptools>=69"]
build-backend = "setuptools.build_meta"

[project]
name = "orgmetra-job-qualification-rule-review"
version = "0.1.0"
description = "Governed Job qualification-rule review evidence for Orgmetra."
requires-python = ">=3.12"

[project.optional-dependencies]
test = ["pytest>=8.3", "pytest-cov>=5.0"]

[tool.setuptools.packages.find]
where = ["src"]

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = [
"--cov=orgmetra_job_qualification_rule_review",
"--cov-branch",
"--cov-report=term-missing",
"--cov-fail-under=100",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Public contract for governed Job qualification-rule review evidence."""

from .review import (
JobQualificationRuleReviewPacket,
build_job_qualification_rule_review_packet,
)

__all__ = [
"JobQualificationRuleReviewPacket",
"build_job_qualification_rule_review_packet",
]
Loading
Loading