Skip to content

README: Cohort

Purpose

This document defines the KNAT application profile for a Cohort — a named, stable group of entities whose membership is determined by evaluating a composable Rule against entity traits.

The goal of this profile is to allow KNAT clients to:

  • read the current census membership for a named cohort
  • monitor evaluation timing and staleness of the census
  • subscribe to membership changes across the cohort evaluation interval
  • join cohort membership to other surfaces (biologic, jook, stele, game)

This profile intentionally does not model:

  • per-frame entity physics or chem state (those are biologic/participant surfaces)
  • the rule definition itself (that is the cohort spec document)
  • governance or consent scoping (those are handled by the fiction/rule surface)

Conceptual Model

A cohort is a dynamic group defined once in a spec document and evaluated on a schedule by the collation coordinator. The coordinator holds a CohortRegistry and re-evaluates each cohort's rule against current EntityTraits every N frames (or on an adaptive schedule).

Cohort Spec (cohort/v1/spec)
    defines: name, rule, description

Collation Coordinator
    holds: CohortRegistry
    evaluates: rule against EntityTraits
    publishes: CohortEvaluationComplete event

Cohort Census (cohort/v1/runtime)
    exposes: members, evaluated_at_frame, staleness

The membership list is stable between evaluations. Consumers that need frame-accurate membership should track is_stale and staleness_frames.

Trait Paths: Rules reference entity traits using dot-separated paths (e.g. role.executor, jook.market-square-beat.in_field). Traits are injected into the entity's EntityTraits map by world items (jooks inject proximity traits; executors inject role traits; etc.) before cohort evaluation.


Root Graph

A cohort KNAT surface is rooted at:

/cohort::<cohort_name>/

Top-level families:

/cohort::<cohort_name>/
    /census
    /frame

The view field on the snapshot indicates whether the surface is complete (full) or policy-shaped (projected). Consumers must not assume completeness when view is projected.


Census Surface

The evaluated membership for this cohort. Updated on the collation coordinator's evaluation schedule, not per-frame.

/cohort::<cohort_name>/census/members
/cohort::<cohort_name>/census/member_count
/cohort::<cohort_name>/census/evaluated_at_frame
/cohort::<cohort_name>/census/staleness_frames
/cohort::<cohort_name>/census/is_stale
/cohort::<cohort_name>/census/aggregates
node type capabilities
members Array read
member_count Integer read
evaluated_at_frame Integer read
staleness_frames Integer read
is_stale Boolean read
aggregates Object read

members is an array of stable string identifiers (participant ids, entity ids). The array is replaced in full on each evaluation; there is no patch/diff format at this surface.

is_stale is true when staleness_frames exceeds the coordinator's configured evaluation interval for this cohort. Consumers polling a stale census should not take high-confidence actions based on membership.

aggregates is optional and contains computed statistics over the current membership (e.g. avg_dissonance, total_dust). Aggregates are only present when the coordinator is configured to compute them for this cohort.


Frame Surface

/cohort::<cohort_name>/frame
node type capabilities
frame Integer read

Simulation frame number at snapshot time.


Staleness Semantics

Cohort evaluation is not per-frame. The coordinator evaluates each cohort on one of two schedules:

  • Fixed interval: every N frames (CohortSchedule::every_n_frames(n))
  • Adaptive: every N frames unless the entity set has changed significantly, in which case re-evaluate sooner (CohortSchedule::adaptive(interval, delta_threshold))

When is_stale is true:

  • members reflects the state from evaluated_at_frame, not the current frame
  • membership changes since evaluated_at_frame are not yet reflected
  • staleness_frames indicates how out-of-date the census is

Consumers that need membership guarantees should either:

  1. Wait for the next CohortEvaluationComplete event before acting, or
  2. Track is_stale and degrade gracefully when census data is approximate

Cross-Domain Joins

From Via To
census/members[] biologic surface participant location, chem state, role
cohort name (as cohort_id) jook surface jook census — same membership, with perception_strength
cohort name (as cohort_id) stele surface stele participants
cohort spec name cohort/v1/spec rule definition, description

Snapshot Format

A full cohort runtime snapshot matches the shape defined in cohort/v1/runtime.json. Key points:

  • census.members is the complete membership array at last evaluation time
  • census.is_stale indicates whether the evaluation interval has been exceeded
  • aggregates is optional and may be absent if not configured
  • The snapshot does not include the rule definition — read cohort/v1/spec for that