<!-- normative -->

# Work Graph

The work structure is not merely a tree and not merely a dependency graph. It is a hierarchical work graph with typed
relations.

## Canonical relation types

Initial authoritative relation types are defined in [Relation types](glossary.md#relation-types).

Relations have identifiers, versions, provenance, and policy metadata where applicable.

`CHILD_OF` is the canonical representation of hierarchy. A node record does not duplicate `parent_id`.

`PRODUCES_FOR` and `INTEGRATES` are the canonical representations of contribution and integration responsibility.
Artefact records may contain projections of these relations for query convenience, but projections are derived and are
not independently mutable.

Blocking is an attribute of a dependency or conflict, not a separate `BLOCKS` relation.

Invalidation is an event and freshness transition caused by a changed input, supersession, conflict, or policy decision.
It is not represented by a separate `INVALIDATES` relation.

`SUPERSEDES` records that one immutable node, contract, or artefact version replaces another. Supersession may cause
invalidation, but the two concepts are not interchangeable.

## Hierarchy and dependency are separate

CHILD_OF means that a child satisfies part of a parent obligation. DEPENDS_ON means that execution or acceptance
requires another result. A node may depend on another node outside its decomposition hierarchy.

## Lazy expansion

The graph is expanded only when additional structure is needed to:

- make a node executable;
- make completion verifiable;
- isolate failure or risk;
- reduce context;
- expose safe parallelism;
- reuse an existing capability;
- perform an informative experiment.

Distant work remains coarse until activation or evidence makes further detail useful.

## Bounded fan-out

Decomposition has bounded local breadth but arbitrary necessary logical depth.

Suggested initial defaults:

```yaml
decomposition:
  preferred_children: 3
  maximum_children: 6
  maximum_active_children_per_node: 4
```

These are safeguards, not correctness rules. If more responsibilities are required, cohesive intermediate nodes may be
introduced. Artificial grouping created only to obey the limit is prohibited.

## Cohesion test

An internal node is justified only if:

- it represents a recognisable responsibility;
- its children share relevant context or constraints;
- it has a useful output or acceptance boundary;
- its parent can evaluate it without understanding every descendant;
- grouping reduces complexity or improves isolation.

## Node Contract

A node is an objective with a versioned contract.

```yaml
node:
  id: NODE-001
  version: 1
  goal: "Produce a verified project outcome"

  contract:
    inputs: []
    outputs: []
    inherited_constraints: []
    inherited_invariants: []
    assumptions: []
    decision_authority: []
    owned_scope: []
    resource_requirements: []
    dependency_conditions: []
    acceptance_criteria:
      - id: AC-001
        description: "The candidate satisfies the declared functional requirements"
        mandatory: true
    validation_procedures: []
    risk_classification: MEDIUM
    provenance_requirements: []
    budget_id: BUDGET-001

  lifecycle_state: PROPOSED
```

## Required fields

Every active node should define:

- goal;
- contract version;
- input references and versions;
- required outputs;
- inherited constraints;
- inherited invariants;
- assumptions;
- delegated decision authority;
- owned scope;
- resource requirements;
- dependency conditions;
- acceptance criteria;
- validation procedures;
- risk classification;
- provenance requirements;
- budget;
- integration ownership;
- publication ownership, where applicable.

## Decision authority

A child must know which decisions it may make autonomously.

Examples:

- internal implementation choices;
- product behaviour;
- interface changes;
- schema publication;
- budget subdelegation;
- dependency upgrades;
- security exceptions.

Product-, safety-, policy-, and externally visible decisions require explicit delegated authority.

## Input freshness

Result freshness is defined in [Result freshness](control-plane.md#result-freshness). Freshness is a property of a
versioned result or acceptance record and is independent from node lifecycle; a node has no freshness field.

## Decomposition

### Reasons to decompose

A node may be decomposed when doing so is expected to improve:

- executability;
- verifiability;
- failure isolation;
- risk containment;
- context reduction;
- safe parallelism;
- reuse;
- information gain;
- model or tool fit.

### Costs of decomposition

A decomposition also introduces:

- coordination cost;
- contract-definition cost;
- integration cost;
- intermediate artefacts;
- context-transfer loss;
- cross-node inconsistency risk;
- additional validation;
- scheduling overhead;
- budget fragmentation.

### Decomposition criterion

Use a structured comparison rather than assuming smaller work is better:

Expected benefits:

- executability
- verifiability
- failure isolation
- risk containment
- context reduction
- safe parallelism
- reuse
- information gain
- model or tool fit

Expected costs:

- coordination
- contracting
- integration
- validation
- intermediate artefacts
- inconsistency risk

Initially, ordinal low, medium, and high assessments are sufficient.

### Deterministic decomposition acceptance

Every acceptance criterion in a node contract has a stable criterion identifier.

Each proposed child declares criterion coverage:

```yaml
criterion_coverage:
  - criterion_id: AC-001
    child_id: NODE-011
    mandatory_cover: true
```

A proposed decomposition is accepted only if:

- every mandatory parent criterion has at least one mandatory covering child;
- every referenced criterion and child exists in the proposal;
- mandatory and optional children are distinguished;
- child contracts are complete and meaningful;
- dependencies are declared;
- interfaces are compatible or typed conflicts are declared;
- an explicit integration action and integration owner are declared;
- parent-level validation remains possible and is not delegated away;
- fan-out and budget policies pass;
- no hierarchy or dependency cycle is introduced;
- every child declares a deterministic owned scope;
- children with provably disjoint repository write scopes may be concurrently eligible;
- children whose scopes overlap, or whose disjointness cannot be proved, remain a valid decomposition but are serialised
  in deterministic scheduling order;
- mutation authority and expected graph version are valid.

Scope overlap is not, by itself, a decomposition-admission failure. It is a scheduling constraint. A decomposition is
rejected only when scope ownership is absent, ambiguous, outside delegated authority, or incompatible with a mandatory
contract invariant.

Semantic coverage review is evidence rather than an unconditional decomposition gate. Deterministic identifier coverage
remains mandatory for every risk level.

For `LOW` and `MEDIUM` nodes, semantic coverage review is advisory unless another frozen policy explicitly requires it.

For `HIGH` and `CRITICAL` nodes, decomposition policy may require an independent semantic coverage review. When the
applicable frozen policy requires that review, its presence and policy-compatible outcome are admission guards and
therefore block atomic decomposition admission. The reasoning component does not admit the decomposition; the
deterministic controller evaluates the review evidence against policy.

If the maximum child count would be exceeded, the proposal must either introduce a cohesive intermediate node that
passes the cohesion test or be rejected. Reaching the fan-out limit is not a valid reason to stop widening while
obligations remain uncovered.

### Graph mutation protocol

```text
Reasoning components may propose expansion but cannot apply it.
Graph mutation proposal
        |
Schema validation
        |
Authority and expected graph-version validation
         |
Cycle and fan-out validation
         |
Budget and policy validation
         |
Deterministic coverage gate
         |
Semantic coverage evidence collection and policy evaluation, when required by the node's risk class
         |
Atomic application
        |
New graph version
```

A proposal produced against an obsolete graph version becomes stale or requires revalidation.

## Executability and Decomposition Stopping

Stop descending when:

- a reliable executor exists;
- required inputs are sufficiently specified;
- the output contract is clear;
- completion can be validated adequately for the risk;
- the work fits executor context and resource limits;
- further decomposition has lower expected value than its cost.

Stop widening when:

- mandatory children cover every mandatory parent acceptance criterion;
- additional siblings provide little incremental parallelism or isolation;
- more children would increase coordination excessively;
- remaining concerns fit coherently within existing children.

If satisfying mandatory coverage would exceed the configured fan-out limit, introduce one or more cohesive intermediate
nodes or reject the decomposition. Do not stop with uncovered obligations.

Depth and node limits are safety guards. Reaching a guard does not prove completion. It yields `BLOCKED`,
`REPLAN_REQUIRED`, `INFEASIBLE`, or `BUDGET_EXHAUSTED` according to deterministic policy.

## Actions and Scheduling

The scheduler schedules actions, not abstract nodes.

Possible actions include:

- PROPOSE_DECOMPOSITION
- EXECUTE
- VALIDATE
- INTEGRATE
- PUBLISH
- REVIEW
- RESOLVE_CONFLICT
- SELECT_ALTERNATIVE
- REPLAN
- CANCEL

## Logical readiness

An action is logically ready when:

- required predecessors are accepted;
- dependency predicates are satisfied;
- required inputs exist;
- blocking product or policy decisions are resolved;
- the node is in a state permitting the action.

## Operational readiness

An action is operationally ready when:

- input and contract versions are current;
- an eligible executor is available;
- permissions allow execution;
- owned and production scopes are compatible;
- isolation requirements can be provided;
- resource capacity is available;
- hierarchical budget permits execution;
- no blocking conflict applies;
- risk and evidence policies permit execution.

## Parallel scheduling

All logically and operationally ready actions may run concurrently, subject to:

- global concurrency;
- per-executor concurrency;
- resource limits;
- scope isolation;
- conflict relations;
- budget commitments;
- dependency conditions;
- alternative-group policy.

Concurrency is an optimisation, not a requirement. The scheduler may serialise work when isolation or integration risk
is uncertain.

## Scheduling inputs and decisions

Executor registration, executor availability, executor loss, capacity grants, capacity releases, resource changes,
scheduling decisions, dispatch acknowledgements, and timer firings are authoritative events.

The scheduler may compute a proposed decision from current state, but no attempt becomes reserved or running until the
corresponding event is admitted.

Required scheduling event types include:

- `EXECUTOR_REGISTERED`
- `EXECUTOR_LOST`
- `CAPACITY_GRANTED`
- `CAPACITY_RELEASED`
- `ACTION_RESERVED`
- `ACTION_DISPATCHED`
- `DISPATCH_ACKNOWLEDGED`
- `CANCELLATION_REQUESTED`
- `TIMER_SCHEDULED`
- `TIMER_FIRED`

The reducer never reads an executor registry, worker queue, resource monitor, or clock directly.

Concurrent repository-writing actions require deterministically disjoint `owned_scope` path sets. If disjointness cannot
be proved before dispatch, those actions must be serialised.
