Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
d1938ef
test(workforce): add RED bitemporal composition-change contract
seonghobae Aug 20, 2026
9df8894
feat(workforce): add same-cutoff composition change evidence
seonghobae Aug 20, 2026
687f1cb
feat(workforce): export composition change contract
seonghobae Aug 20, 2026
b4c6725
refactor(workforce): type same-cutoff comparison coordinate
seonghobae Aug 20, 2026
72cae07
docs(adr): define same-cutoff workforce change boundary
seonghobae Aug 20, 2026
055a926
docs(doctoring): record current workforce-change sources
seonghobae Aug 20, 2026
89eb7e9
docs(traceability): map workforce composition change evidence
seonghobae Aug 20, 2026
7a8b63c
docs(hris-kernel): explain same-cutoff workforce change evidence
seonghobae Aug 20, 2026
3649873
docs(hris-kernel): add package changelog
seonghobae Aug 20, 2026
407593a
test(workforce): reject inconsistent aggregate evidence
seonghobae Aug 20, 2026
4b5f5dd
fix(workforce): fail closed on inconsistent aggregate evidence
seonghobae Aug 20, 2026
8405a31
chore: integrate protected develop into workforce-change lane
seonghobae Aug 20, 2026
1e8af74
chore: reconcile workforce composition change with current develop
seonghobae Aug 20, 2026
8d4958e
Merge protected develop into workforce composition branch
seonghobae Aug 20, 2026
db4ea77
docs: remove trailing whitespace from workforce ADR
seonghobae Aug 21, 2026
d38f7e8
test(workforce): reject invalid aggregate evidence types
seonghobae Aug 21, 2026
9269c34
fix(workforce): validate aggregate evidence types before arithmetic
seonghobae Aug 21, 2026
58a956f
docs(workforce): record aggregate evidence type hardening
seonghobae Aug 21, 2026
4184e92
fix(hris): restore workforce resolution contracts
seonghobae Aug 21, 2026
7d50e77
chore(workforce): integrate protected develop after #43
seonghobae Aug 21, 2026
8f948a2
test(workforce): reject temporal evidence subclasses
seonghobae Aug 21, 2026
1425d39
fix(workforce): validate exact temporal evidence types
seonghobae Aug 21, 2026
00b51a8
test(workforce): reject forged change endpoint types
seonghobae Aug 21, 2026
cc6784e
fix(workforce): require exact change endpoint evidence types
seonghobae Aug 21, 2026
4a1e907
fix(workforce): validate snapshot tenant identity
seonghobae Aug 28, 2026
0e3f432
fix(workforce): freeze composition evidence boundaries
seonghobae Aug 29, 2026
e819091
fix(hris): reject impossible workforce staffing totals
seonghobae Aug 29, 2026
8b4aa1d
docs: trace workforce staffing invariants
seonghobae Aug 29, 2026
6ada6de
fix(hris): reconcile assigned workforce people
seonghobae Aug 29, 2026
c27a9f6
fix(hris): make workforce FTE deltas deterministic
seonghobae Aug 29, 2026
d829fba
fix(hris): make workforce FTE aggregation exact
seonghobae Aug 29, 2026
fd39e07
fix(hris): enforce exact allocation limits
seonghobae Aug 29, 2026
e6e85c8
test(hris): reproduce allocation and evidence integrity gaps
seonghobae Aug 30, 2026
47020aa
fix(hris): bound assignment allocation scale
seonghobae Aug 30, 2026
bc02174
fix(workforce): revalidate canonical aggregate evidence
seonghobae Aug 30, 2026
786706f
test(hris): cover allocation type and finiteness guards
seonghobae Aug 30, 2026
8971be2
test(hris): treat allocation limits as literal evidence
seonghobae Aug 30, 2026
90632c6
test(hris): escape allocation-limit assertions
seonghobae Aug 30, 2026
9331d8b
docs(hris): record evidence export and allocation hardening
seonghobae Aug 30, 2026
f349348
docs(adr): harden workforce evidence trust boundary
seonghobae Aug 30, 2026
438d84d
docs(traceability): bind workforce export invariants to regressions
seonghobae Aug 30, 2026
fce4e7d
docs(changelog): record workforce integrity repairs
seonghobae Aug 30, 2026
4bc4933
chore(manifest): regenerate foundation inventory
seonghobae Aug 30, 2026
c08de57
test(workforce): reproduce direct FTE canonicalization gaps
seonghobae Aug 30, 2026
5b39b0d
fix(workforce): canonicalize four-decimal FTE evidence
seonghobae Aug 30, 2026
2fa8a22
test(workforce): align FTE validation contract
seonghobae Aug 30, 2026
edca948
test(workforce): cover canonical FTE export scale
seonghobae Aug 30, 2026
8a99993
docs(adr): canonicalize workforce FTE evidence scale
seonghobae Aug 30, 2026
9d18b65
docs(hris): record canonical FTE scale contract
seonghobae Aug 30, 2026
6dc0f3d
docs(traceability): bind canonical FTE scale to evidence
seonghobae Aug 30, 2026
453bef0
test(workforce): cover canonical evidence mutation gaps
seonghobae Aug 30, 2026
9979b73
fix(workforce): canonicalize aggregate evidence safely
seonghobae Aug 30, 2026
40058a5
fix(workforce): revalidate comparison coordinates at export
seonghobae Aug 30, 2026
730685e
test(workforce): cover hardening branches
seonghobae Aug 30, 2026
712238b
test(workforce): assert status-domain validation
seonghobae Aug 30, 2026
aaf63ab
docs(traceability): record workforce evidence hardening
seonghobae Aug 30, 2026
bec1443
docs(traceability): bind change export revalidation
seonghobae Aug 30, 2026
672ce23
docs(changelog): record canonical evidence repair
seonghobae Aug 30, 2026
9a04f9d
test(workforce): reproduce malformed endpoint date leak
seonghobae Aug 30, 2026
1fedd6c
fix(workforce): validate endpoints before comparison
seonghobae Aug 30, 2026
6726d05
fix(provenance): refresh workforce ADR manifest evidence
seonghobae Aug 30, 2026
d6233a7
docs(workforce): trace canonical evidence hardening tests
seonghobae Aug 30, 2026
90e2cff
fix(provenance): refresh workforce ADR manifest evidence
seonghobae Aug 30, 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
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ All notable changes to Orgmetra will be documented in this file.
- Active-PR `orgmetra_selection_review` packet for PII-minimized, evidence-bound human selection review: canonical operational tenant identity, UUID-backed opaque candidate/Job/sealed-evidence/reviewer references, explicit purpose/reason/evidence version, deterministic canonical JSON and SHA-256 correlation, mandatory human decision state, redacted packet repr, and provenance-paired model evidence that remains `untrusted_draft`, with exact 100% owned statement and branch coverage required by its quality gate.
- Active performance-criterion scope hardening: `criterion_observation_scope_guard` rejects criterion outcomes for a Job the worker did not effectively hold at the observation date, observations before the relevant assignment, and observations outside the referenced performance cycle while preserving valid multiple-assignment cases and existing bitemporal correction semantics. The guard evaluates current-recorded facts, derives the date coordinate from `observed_at` in UTC so session `TimeZone` cannot alter the result, uses a trusted function search path, and adds no PII or automated employment decision authority. The Foundation PostgreSQL contract also rejects a closed `recorded_to` on each time-coordinate lookup and proves UTC midnight plus non-UTC session `TimeZone` boundaries.
- Bitemporal tenant-scoped organization hierarchy validation that rejects visible indirect parent cycles and reuses single-valued recorded-time reconstruction before graph traversal.
- Active-PR workforce composition evidence now freezes caller-owned knowledge cutoffs to exact UTC instants, detaches status-count containers before digesting, and resolves one cutoff before both change endpoints so mutable timezone providers cannot rewrite aggregate evidence.
- Stacked governed job-analysis evidence contract via `JobAnalysisSnapshot`, `TaskEvidence`, `KSAORequirement`, `TaskKSAOLink`, `FunctionalJobAnalysisProfile`, and `EvidenceSource`: tenant/Job-scoped observable tasks, explicit Task-to-KSAO linkage, importance/difficulty/proficiency ratings, source/version/retrieval/SHA-256 provenance, deterministic canonical snapshot bytes, current O*NET evidence support, and historical DOT Data/People/Things compatibility. Validated snapshots require accountable human review and complete non-LLM evidence; LLM-origin material remains `analysis_draft`, and the snapshot is evidence input rather than a hiring, promotion, termination, compensation, or other high-impact employment decision.
- Stacked governed audit/outbox slice via `AuditOutboxEvent`, `audit_event_record`, `outbox_delivery_record`, and `outbox_delivery_escalation_record`: CloudEvents 1.0-compatible PII-minimized metadata, exact canonical JSON bytes, database-verified SHA-256 digests, mandatory human confirmation for high-impact events, immutable audit evidence, tenant RLS, atomic audit/outbox insertion, guarded pending/leased/delivered/dead-lettered delivery state, tenant-safe `claim_outbox_delivery(...)` with deterministic due-work ordering, `FOR UPDATE ... SKIP LOCKED`, opaque worker identity, bounded future leases, immutable envelope return, and atomic takeover of genuinely expired leases only while retry attempts remain; owner-bound `complete_outbox_delivery(...)` and `retry_outbox_delivery(...)`; database-budget-governed `dead_letter_outbox_delivery(...)`; and a separately privileged `operator_dead_letter_expired_outbox_delivery(...)` recovery path for an exhausted final lease whose recorded worker identity is permanently unavailable. `maximum_attempt_count` is persisted on the delivery row, defaults to 5, is constrained to 1 through 100, and cannot be lowered by a dispatcher during finalization. Migration 0007 prevents retry or expired-lease takeover from creating attempt N+1; migration 0008 adds TRUNCATE guards, trusted function search paths, a concurrently built due-work partial index, session-independent immutable envelope validation, and operator recovery backed by separate NOLOGIN/NOBYPASSRLS owner/capability roles so the externally assignable operator role can invoke recovery without receiving direct transport-table read/write rights. Migration 0008 also rejects pre-existing reserved recovery-role names before project DDL, atomically contains the temporary schema-creation privilege used for function ownership handoff, and forces deferred escalation binding while the narrow SECURITY DEFINER owner is still active. Exponential/backoff policy selection, policy-specific producer configuration, and external delivery receipts remain subsequent work.
- `orgmetra_hris_kernel` 0.4.0 with exclusive-versus-concurrent employment, staffable position coverage, exclusive-seat capacity, and `validate_assignment_write` at 100% statement and branch coverage.
Expand Down Expand Up @@ -53,9 +54,11 @@ All notable changes to Orgmetra will be documented in this file.
- Made assignment coverage status-aware: `active` and `leave` remain staffable while `terminated` and other non-eligible employment statuses fail closed.
- Made organization hierarchy reconstruction fail closed on a cycle at the requested tenant, effective day, and knowledge cutoff while ignoring future-recorded and foreign-tenant facts.
- Build the outbox due-work index concurrently during migration 0008, requiring that index step to run outside an explicit transaction block so established queues do not block writers while the index is built; pre-index hardening and post-index privileged role setup use separate explicit transactions.
- Workforce allocation validation now requires exact finite Decimal ratios in `(0, 1.0000]` with at most four fractional places before exact employment-portfolio or Position-seat aggregation, keeping the kernel aligned with persisted allocation scale and bounded arithmetic.

### Security

- Workforce canonical JSON and digest export now revalidate the full temporal, tenant, status, count, staffing, and reconciliation contract immediately before serialization, so post-construction low-level mutation cannot mint contradictory aggregate evidence.
- Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security.
- Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII.
- LLM output constrained to draft evidence.
Expand All @@ -73,4 +76,4 @@ All notable changes to Orgmetra will be documented in this file.

### Notes

- Protected `develop` at `e7ddb7a78a5e1460410005d10f43ebf18c5e12e4` includes normalized validity-study and criterion integrity, bitemporal workforce composition, governed candidate-to-worker conversion, purpose-bound PII authorization, GET-only People reads, governed People mutation/idempotency API, and the accepted ADR 0001–0003 source expansion integrated by #37. Job Analysis persistence/API and the selection-review packet remain active-PR truth until their unchanged exact heads satisfy fresh gates and merge.
- Protected `develop` at `9e3e4847510e1e612b48474ba42b177b8ed824df` includes the merged workforce-composition baseline from #33. Same-cutoff workforce change evidence and the export/allocation hardening in #54 remain active-PR truth until the unchanged exact head satisfies fresh required gates and independent review; predecessor PR or workflow evidence does not transfer.
11 changes: 9 additions & 2 deletions docs/adr/0011-bitemporal-workforce-composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Status

Accepted on active PR #33 only. This document is not protected-`develop` product truth until the owning PR integrates.
Accepted on protected `develop` through merged PR #33. Active PR #54 strengthens the accepted contract's deterministic arithmetic and canonical-evidence integrity; those strengthening changes are not protected-`develop` truth until #54 integrates.

## Context

Expand All @@ -19,9 +19,16 @@ Orgmetra will expose a pure `WorkforceCompositionSnapshot` derived from authorit
- Employment count preserves the number of visible reportable employment relationships.
- Before aggregation, the snapshot reuses the HRIS employment-concurrency invariant at the report coordinate. Two overlapping `exclusive` employments or an unknown concurrency code fail closed instead of being normalized into plausible headcount.
- Staffed assignment count and staffed FTE are computed from visible assignments after reusing the existing assignment-to-employment coverage, per-employment allocation, and position-seat capacity integrity rules.
- Direct aggregate construction repeats the resulting staffing relationships: zero assignments require zero FTE and zero assigned people, staffed assignments require positive FTE and reportable employment/person totals, assigned people cannot exceed assignments, and staffed FTE cannot exceed the assignment count.
- One overfilled Position seat therefore remains a data-integrity failure even when the aggregate FTE total itself looks plausible.
- Unassigned-person count surfaces a buyer-actionable staffing gap without serializing row-level worker identity.
- Status counts are aggregate employment evidence, sorted deterministically.
- The snapshot freezes the timezone-aware knowledge cutoff to an exact UTC datetime and detaches status-count containers before validation, so mutable caller objects cannot change canonical evidence after construction.
- Staffed FTE evidence is accepted only as an exact finite non-negative `Decimal` with at most four fractional places and is canonicalized to exactly four fractional places at construction; canonical export requires that fixed scale again. Equivalent values such as `0.5` and `0.5000` therefore serialize and hash identically, while extreme-scale direct evidence cannot reach comparison arithmetic.
- Canonical JSON and digest export re-run the same non-mutating temporal, tenant, status, count, staffing, and reconciliation invariants used after construction, so low-level runtime mutation cannot silently mint contradictory workforce evidence.
- Endpoint FTE totals and workforce-change deltas align finite Decimal coefficients before arithmetic, so the caller's ambient Decimal precision cannot change endpoint evidence, the reported delta, canonical JSON, or content digest.
- Employment-portfolio and Position-seat limits use the same exact Decimal coefficient total, so low caller precision cannot admit an overallocated staffing total.
- Allocation rows must be exact finite `Decimal` values in `(0, 1.0000]` with no more than four fractional places before exact coefficient aggregation. This keeps the kernel aligned with the People/API persistence scale contract and prevents hostile or accidental extreme exponents from creating unbounded integer-coefficient work.
- Two visible versions of one Employment or Assignment identity fail closed. Invalid assignment coverage or over-allocation remains a data-integrity error rather than becoming a plausible metric.
- The canonical JSON contains the opaque tenant identifier, report coordinates, aggregate metrics, and schema version only. It excludes person, employment, assignment, and position identifiers and all human-readable PII.
- SHA-256 addresses the exact canonical UTF-8 representation so a caller can correlate a report with immutable audit evidence without copying source rows.
Expand All @@ -46,7 +53,7 @@ Orgmetra will expose a pure `WorkforceCompositionSnapshot` derived from authorit

## Verification

`packages/hris-kernel/tests/test_workforce_composition.py`, `packages/hris-kernel/tests/test_workforce_composition_boundaries.py`, and `packages/hris-kernel/tests/test_workforce_position_capacity.py` require tenant isolation, concurrent-employment person deduplication, active/leave composition, terminated exclusion, future-effective and late-recorded exclusion, FTE and unassigned-person reporting, deterministic canonical evidence, historical recorded-time reconstruction, duplicate-version rejection, overlapping-exclusive-employment rejection, position-seat over-allocation rejection, assignment-person integrity, per-employment allocation-integrity reuse, and timezone-aware knowledge cutoffs. `.github/workflows/workforce-intelligence-quality.yml` checks out the exact candidate SHA and runs the complete HRIS kernel with the package's 100% statement and branch coverage threshold.
`packages/hris-kernel/tests/test_workforce_composition.py`, `packages/hris-kernel/tests/test_workforce_composition_boundaries.py`, `packages/hris-kernel/tests/test_workforce_position_capacity.py`, `packages/hris-kernel/tests/test_workforce_composition_change.py`, `packages/hris-kernel/tests/test_assignment_portfolio.py`, `packages/hris-kernel/tests/test_position_coverage.py`, `packages/hris-kernel/tests/test_allocation_and_snapshot_export_regressions.py`, and `packages/hris-kernel/tests/test_workforce_canonical_evidence_hardening.py` require tenant isolation, concurrent-employment person deduplication, active/leave composition, terminated exclusion, future-effective and late-recorded exclusion, FTE and unassigned-person reporting, deterministic canonical evidence, fixed four-decimal FTE canonicalization, extreme-scale FTE rejection, post-construction export revalidation including scale mutation, context-independent endpoint and workforce-change FTE arithmetic, historical recorded-time reconstruction, duplicate-version rejection, overlapping-exclusive-employment rejection, position-seat over-allocation rejection, low-precision allocation-limit rejection, allocation type/finiteness/scale rejection, assignment-person integrity, per-employment allocation-integrity reuse, and timezone-aware knowledge cutoffs. `.github/workflows/workforce-intelligence-quality.yml` checks out the exact candidate SHA and runs the complete HRIS kernel with the package's 100% statement and branch coverage threshold.

## References

Expand Down
38 changes: 38 additions & 0 deletions docs/adr/0024-same-cutoff-workforce-composition-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# ADR-0024: Workforce composition change uses one recorded-time cutoff

**Status:** Proposed on active PR
**Decision owner:** Orgmetra

## Context

Protected Orgmetra can reconstruct a `WorkforceCompositionSnapshot` for one tenant at an effective business date and an explicit recorded-time knowledge cutoff. Buyers also need to compare workforce composition across two effective dates. A naive comparison can be misleading if the opening snapshot is reconstructed with an earlier knowledge cutoff than the closing snapshot: later corrections then appear indistinguishable from actual business-time workforce movement.

ISO 30414:2025 is the current published second edition of the human-capital reporting and disclosure standard. Its public catalogue lists workforce composition, mobility and succession planning, and workforce turnover among core reporting areas. This ADR uses that public scope only; it does not reproduce licensed metric definitions or claim ISO certification.

## Decision

Orgmetra adds a pure `WorkforceCompositionChangeSnapshot` and builder in the HRIS kernel.

- Both endpoint snapshots must belong to the same authoritative tenant.
- The opening effective date must be strictly earlier than the closing effective date.
- Both endpoint snapshots must use one exact `known_at` recorded-time cutoff. Effective-time change is therefore compared while knowledge time is held constant.
- The builder resolves that cutoff once to a detached UTC datetime before constructing either endpoint; caller-owned timezone providers cannot cause the two endpoint reconstructions to observe different recorded times.
- Each endpoint is built through the existing workforce-composition function, so contradictory bitemporal facts, invalid assignment coverage, impossible employment concurrency, over-allocation, and overfilled Position capacity continue to fail closed before aggregation.
- The comparison exposes net changes in distinct-person headcount, reportable employment count, staffed assignment count, staffed FTE, unassigned-person count, and deterministic per-status counts.
- The contract deliberately does **not** label a net change as a hire, separation, transfer, turnover event, cause, forecast, protected-attribute effect, or recommendation. Those claims require event-specific governed evidence that this aggregate comparison does not possess.
- Canonical JSON embeds only the two aggregate endpoint snapshots, their SHA-256 digests, aggregate deltas, the opaque tenant identifier, and schema version. It does not serialize row-level Person, Employment, Assignment, or Position identifiers.
- The result is descriptive workforce-intelligence evidence only and cannot authorize a high-impact employment action.

## Consequences

Buyers can compare two business dates without silently mixing later-recorded corrections into the change metric. The comparison is deterministic and audit-correlatable while remaining aggregate-only. Because it is intentionally not a turnover calculator, a later turnover/mobility slice must bind authoritative employment-transition evidence and its denominator/period policy explicitly rather than deriving causal labels from endpoint subtraction.

The slice adds no persistence table, dashboard, export endpoint, forecasting model, diversity inference, or automated decision authority. Authorization and presentation remain at their owning boundaries.

## Verification

`packages/hris-kernel/tests/test_workforce_composition_change.py` covers realistic effective-date change, exact Decimal FTE deltas, deterministic source-order independence, aggregate-only canonical evidence, same-tenant enforcement, strictly forward effective dates, and one shared knowledge cutoff. `.github/workflows/workforce-intelligence-quality.yml` runs the complete HRIS kernel at exact 100% owned production statement and branch coverage.

## References

APA 7 references and current public standard metadata are recorded in `docs/doctoring/workforce-composition-change-references.md`.
17 changes: 17 additions & 0 deletions docs/doctoring/workforce-composition-change-references.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Workforce composition change references

## Status

Evidence for the active workforce-composition-change PR. This file does not make the active-PR code protected-`develop` truth before merge.

## APA 7 references

International Organization for Standardization. (2025). *ISO 30414:2025 Human resource management — Requirements and recommendations for human capital reporting and disclosure* (2nd ed.). ISO. https://www.iso.org/standard/30414

International Organization for Standardization. (2022). *ISO 30400:2022 Human resource management — Vocabulary* (2nd ed.). ISO. https://www.iso.org/standard/78044.html

## Exact public evidence used

The ISO catalogue was rechecked on August 20, 2026. ISO 30414:2025 remains the published second edition and lists workforce composition, mobility and succession planning, and workforce turnover among its core human-capital reporting areas; ISO 30414:2018 is withdrawn. ISO 30400:2022 remains the published second-edition HR-management vocabulary standard.

Orgmetra uses only those public catalogue facts as design traceability. The implementation does not reproduce licensed ISO metric definitions, infer a turnover formula from the standard, or claim certification. The same-cutoff bitemporal comparison semantics are independently specified by ADR-0024 and executable Orgmetra tests.
Loading
Loading