Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion notations/CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,12 +397,13 @@ The lifecycle fields are required on every canonical primitive once a notation s

`ELEM-FORMER-ID-001` ([ELEMENT_PRIMITIVES.md](../notations/ELEMENT_PRIMITIVES.md) §9) flags any `former_id` that collides with a live element `id` or another element's `former_ids` — such a collision means Phase 2 was not completed cleanly.

**First-class time-aware relations.** Kinds declared in [the REL specification](elements/17-relations.md) are lifecycle-bearing files in `canon/relations/`, with independent admission and inclusive day windows contained in both endpoint lifecycles. Each host notation declares which links remain inline; there is no blanket inline-only phase. Person reporting uses `reports_to` (REL §3.4).

### 7.5 Out of scope (v1)

- **Bitemporality.** No separate `transaction_time` vs `valid_time`. v1 records what is true *now* about what was true *then*; back-dating corrections rewrite the file via git, and the git history is the audit trail.
- **Branching timelines.** Alternative futures are the concern of the Scenarios notation (`notations/views/reports/11-scenarios.md`), not of the primitive lifecycle.
- **Sub-day precision.** ISO 8601 date precision only; no timestamps, no timezones in canon. "Today" is the date of the query or render.
- **First-class time-aware relations.** Promoting relations like `parent` / `applies_to` / activity→goal to first-class lifecycle-bearing files is planned for Wave 3 of the temporal model. In v1 such relations remain inline and timeless on their host primitive.

---

Expand Down
1 change: 1 addition & 0 deletions notations/ELEMENT_PRIMITIVES.md
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ The active-structure identity primitive — *who or what exists and performs wor
| `external_ref` | no | string | External identifier or URL — e.g. a `system`'s integration endpoint, or an external organisation's reference. |

- **Identity only.** A `person` actor is *who someone is*, independent of engagement. Employment, candidacy, alumni status, community membership, and contracting are **first-class time-aware `REL` records** ([elements/17-relations.md](elements/17-relations.md) §3), not fields here — a person can exist in the org's scope (candidate, alumnus, contractor, community member) without being an employee.
- **Person reporting.** `reports_to` is a first-class time-aware REL from subordinate `ACTOR(person)` to manager `ACTOR(person)`, never an inline manager field. Concurrent unranked managers are valid with a repository-health warning; employment, membership and unit hierarchy imply no reporting link. See [the reporting contract and oracle](elements/17-relations.md#34-reports_to--direct-person-reporting).
- **Org hierarchy.** A `business_unit` actor's parent unit is a time-aware `REL` of `type: unit_parent` (`ACTOR(business_unit) → ACTOR(business_unit)`), not an inline field.
- **Role assignment.** Which `ROLE` an actor fills is carried on the relevant engagement `REL` (e.g. `employment` carries role assignments), not inline on the actor.

Expand Down
78 changes: 76 additions & 2 deletions notations/elements/17-relations.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "Relations — first-class time-aware links"
version: "0.5"
version: "0.6"
author: "Valerii Korobeinikov"
last_updated: "2026-09-24"
last_updated: "2026-10-12"
status: "draft"
---

Expand Down Expand Up @@ -84,6 +84,7 @@ The enum is **closed** in v1. Each value names a specific kind of link between t
| `assessment_influences_goal` | assessment → goal | `ASSESSMENT` → `GOAL` | An assessment (a dated finding about a `DRIVER`) influences a goal — the polarity edge of the ArchiMate motivation chain *Driver → Assessment → influences(±) → Goal*. **All polarity in the motivation model lives here**, not on the assessment node (the assessment records *what is*, this REL records *how it bears on this specific intent*). **M:N**: one assessment may bear on several goals, with opposite signs (one finding can support goal A and threaten goal B — SWOT is goal-relative), and one goal is influenced by many assessments. Required `sign` attribute on the REL file: closed vocabulary `positive` \| `negative` — the direction of the influence (DSM's up/down arrows on goals). Optional `magnitude` attribute: closed vocabulary `low` \| `medium` \| `high` — the strength of the influence; omit when unknown. Each (assessment, goal) pair is its own REL file; same shared REL machinery as `goal_parent`'s multi-parent form and `target_state_satisfies_goal`, not a one-off mechanism. A finding that ceases to bear on a goal (the goal retires, or re-measurement reverses the sign) ends with `valid_to` set; a new REL file carries the new sign. |
| `action_goal` | action → goal | `ACTION` → `GOAL` | An action serves a goal. An action re-aimed mid-stream produces a new relation. **Deprecated alias:** `activity_goal` (accepted with `ACTION-005` warning). |
| `unit_parent` | child → parent | `ACTOR(business_unit)` → `ACTOR(business_unit)` | Organisational re-parenting — a business-unit actor moved under a different parent unit. (Was `UNIT → UNIT` before the 2026-05-29 Actors decision folded `UNIT` into `ACTOR`.) |
| `reports_to` | subordinate → manager | `ACTOR(person)` → `ACTOR(person)` | Direct person reporting, with concurrent unranked managers permitted. Each pair/window is a separate REL; reverse retrieval uses the same records. See §3.4. |
| `employment` | person → org | `ACTOR(person)` → `ACTOR(business_unit)` | Employment of a person by a unit / organisation. Time-aware (the employment window); carries the most attributes of the engagement kinds — `contract_type`, role assignments (`roles: [ROLE-…]`). |
| `candidacy` | person → org | `ACTOR(person)` → `ACTOR(business_unit)` | A person under evaluation (pre-hire). Carries `stage`, `source`. |
| `alumni_membership` | person → org | `ACTOR(person)` → `ACTOR(business_unit)` | A former employee's continuing relationship; may reference the prior `employment`. |
Expand Down Expand Up @@ -176,6 +177,76 @@ What it says, and what it refuses to say:

---

### 3.4 `reports_to` — direct person reporting

A `reports_to` REL states that the subordinate person (`from`) reports directly
to the manager person (`to`). Both endpoints MUST resolve to independently
admitted `ACTOR` records with `type: person`. Employment, unit membership,
role assignment and `unit_parent` retain their existing meanings and never
imply a reporting edge. There is no same-unit or shared-employer prerequisite.
The relationship is binary and M:N: concurrent managers are unranked, with no
primary/functional distinction or allocation percentage. Store no inverse kind
and no canonical inline manager field on ACTOR; free-form `extensions:` remain
pass-through and do not establish reporting authority.

**Time and admission.** Each REL has its own admission record and required
`valid_from` and `valid_to`. Dates are quoted ISO days; the window is inclusive
at both ends, and null end means unbounded, not already active. Equal dates
form a valid one-day window. The entire window MUST fit inside both endpoint
lifecycles (`REL-003`); a null relation end cannot fit a finite endpoint end.
Do not silently clip invalid windows. A draft REL does not become admitted
because its actors are admitted, nor does admitting a REL admit its actors.

**Identity and graph.** Resolve supported identity aliases before comparing
endpoints or counting people. A resolved self-link is `REL-011` (error).
`REL-012` (error) rejects a cycle, including a cycle of three or more persons,
whose admitted, resolved reporting edges are simultaneously effective on any
date. Validate all history by interval change points or by a nonempty common
intersection of the cycle's edge windows and endpoint lifecycles. A union of
historical edges is insufficient: A→B ending June 30 and B→A starting July 1
is valid; starting the second on June 30 creates a cycle on that date. Retain
the ordered actor path, all incident REL IDs and a witness date/overlap interval
in the diagnostic. Traversals must terminate with a visited set; invalid data
must not produce a fabricated hierarchy.

**Direct queries at date D.** Resolve identities, require admission and valid
contained windows, and select edges for which both endpoints and the REL are
in effect at D. `managers(A, D)` groups matching `from=A` edges by resolved `to`;
`directReports(B, D)` groups matching `to=B` edges by resolved `from`. Return
deterministically ordered distinct identities with **all contributing REL IDs**
for each pair. Listing and trace must use the same population. No transitive
management inference is required. Zero edges means “no reporting relationship
recorded”, not proof that the person has no manager. An unresolved/unadmitted
endpoint produces `REL-002`; an incomplete or unreadable catalogue produces an
explicit incomplete result, never a clean empty answer or health success.

**Matrix warning and evidence.** A repository-health scan emits `REL-013`
(warning) when a person has more than one distinct concurrently effective
manager. Include the person, manager identities, contributing REL IDs and
witness date/overlap window. A dated scan evaluates D; an all-history scan
checks interval change points. This warning does not invalidate the otherwise
valid matrix relationship. Multiple records for one resolved manager do not
trigger it. Preserve authored evidence IDs and windows, including disjoint
recurrence of the same pair; ingest deduplication must not discard recurrence
merely because kind/from/to already appeared.

**Specification and compatibility boundary.** The [synthetic consumer example
and acceptance oracle](../examples/relations/reports-to/) specify expected
results and positive/negative vectors. This is an additive MINOR contract
change (relation spec 0.6); it allocates `REL-011`–`REL-013` under
[diagnostic identity rules](../CONTRACT.md#187-versioned-diagnostic-identity).
The new errors apply only to the newly introduced kind. Existing codes, meanings
and severities are unchanged. Existing records need
no migration. Older pinned vocabularies/validators can reject `reports_to`
as an unknown kind; a current vocabulary loader recognizing the token is not
proof of subtype, temporal, graph or query enforcement. The methodology release
pin remains unchanged until release preparation; no package is released here.
Dependent validators, ingest and query consumers must bind conformance evidence
to the delivered specification revision and diagnostic allocation. These rules
and example are not a claim of released or installed runtime support.

---

## 4. File location and naming

```
Expand Down Expand Up @@ -208,6 +279,9 @@ A typical naming convention encodes the endpoints and kind in the middle segment
| `REL-008` | warning | A cycle exists in the `process_parent` graph among admitted REL files (A is a child of B … is a child of A). Cross-cutting — fires when the catalogue is loaded. Warning rather than error because a genuine mutual embedding is unusual but not always a data error. Kind-specific, parallel to `REL-006`; that code is not widened. |
| `REL-009` | error | A `requirement_parent` REL has identical `from` and `to`. Applies to the requirement-chain extension. |
| `REL-010` | warning | A cycle exists in the active union of inline `REQUIREMENT.parent` and `requirement_parent` REL edges at the as-at date, including an inline self-parent. Cross-cutting; retain every incident cycle edge and terminate traversal. Applies to the requirement-chain extension; does not widen `REL-006` or `REL-008`. |
| `REL-011` | error | A `reports_to` REL resolves both endpoints to the same person, including supported identity aliases. Report the REL ID and resolved person ID. |
| `REL-012` | error | A cycle of admitted `reports_to` edges is simultaneously effective on some date, including 3+ person cycles. Report the ordered actor path, incident REL IDs and witness date/overlap interval (§3.4). |
| `REL-013` | warning | A repository-health scan finds more than one distinct concurrently effective manager for a person. Report identities, contributing REL IDs and witness date/window; duplicate evidence for one manager does not trigger this warning (§3.4). |

For the requirement-chain extension, inline `parent`/`serves` and active matching
REL records form an additive union. An identical pair is one logical edge with
Expand Down
11 changes: 8 additions & 3 deletions notations/elements/19-actors.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "Actors — active-structure identity primitive"
version: "0.1"
version: "0.2"
author: "Valerii Korobeinikov"
last_updated: "2026-05-29"
last_updated: "2026-10-12"
status: "draft"
---

Expand Down Expand Up @@ -102,12 +102,17 @@ All of an actor's links are first-class, time-aware `REL` records ([17-relations
| Relation `type` | From → To | What it records |
|---|---|---|
| `unit_parent` | `ACTOR(business_unit)` → `ACTOR(business_unit)` | Org hierarchy — a unit's parent unit. Re-parenting = one ended relation + one new. |
| `reports_to` | `ACTOR(person)` → `ACTOR(person)` | Direct subordinate → manager; concurrent unranked managers are valid with a health warning. See [reporting contract](17-relations.md#34-reports_to--direct-person-reporting). |
| `employment` | `ACTOR(person)` → `ACTOR(business_unit)` | Employment window; carries `contract_type` and role assignments (`roles: [ROLE-…]`). |
| `candidacy` | `ACTOR(person)` → `ACTOR(business_unit)` | Pre-hire evaluation; carries `stage`, `source`. |
| `alumni_membership` | `ACTOR(person)` → `ACTOR(business_unit)` | Former-employee relationship; may reference the prior `employment`. |
| `community_membership` | `ACTOR(person)` → `ACTOR(business_unit)` | Membership of a community modelled as a `business_unit` actor. |
| `contracting` | `ACTOR(person\|business_unit)` → `ACTOR(business_unit)` | Contracting relationship; carries `contract_terms`. |

Reporting is independent of employment and unit hierarchy; neither implies a manager.
Use a separate REL for each pair/window, preserving recurrence. Do not interpret
free-form `extensions:` as canonical reporting fields or reject their pass-through.

Action ownership references an actor by ID: an action's `owner: ACTOR-…` ([07-action.md](../views/diagrams/07-action.md) §5.6). The Stakeholders notation references an actor for identity (`STAKEHOLDER.actor: ACTOR-…`, REQUIRED) — a stakeholder carries the stake, never the identity.

---
Expand All @@ -130,7 +135,7 @@ A flat catalogue listing (`*.actors.transitrix.yaml`) is an optional **view** ov
|---|---|---|
| `ACTOR-001` | error | `id` missing or not matching `ACTOR-[<middle>-]<INTEGER>` ([IDS_AND_REFERENCES.md](../IDS_AND_REFERENCES.md) §1); or a required field (`notation`, `name`, `type`, `zone`, `admitted_at`, `admitted_by`, `gate_checks`, `valid_from`, `valid_to`) is missing. |
| `ACTOR-002` | error | `type` is not one of `person`, `business_unit`, `system`. |
| `ACTOR-003` | error | An engagement / hierarchy field (`employment`, `unit_parent`, `roles`, `owner`, …) is present inline on the actor file — these belong in `REL-…` files (`REL-004`), not on the identity primitive. |
| `ACTOR-003` | error | An engagement / hierarchy field (`employment`, `unit_parent`, `reports_to`, `manager`, `roles`, `owner`, …) is present inline on the actor file — these belong in `REL-…` files (`REL-004`), not on the identity primitive. |

The shared header (`HDR-001..004`, [CONTRACT.md](../CONTRACT.md) §2) and primitive-lifecycle (`LIFECYCLE-001..004`, [CONTRACT.md](../CONTRACT.md) §7.3) rules apply to ACTOR files in addition to the ACTOR-* rules above.

Expand Down
Loading
Loading