system actor kind — v0_1
Version. 0.1
Date. 2026-08-20
Status. Open. First CR of the H0 lane (Boundaries handoff Step 4; work order loomworks-cr-brief-h0-native-habitat-v0_1.md §2 W7). Scope is W7 only.
Runtime direction: no conflict — this CR implements O3 (land the system actor kind, migrate the masqueraders) and honors O1 by keeping every migrated write at its named chokepoint (per ruling R1: the sin was the costume, not the attendance).
Rulings shaping this CR. R1 (loomworks-handoff-step-4-v0_1.md): the human-authority gates gain an explicit, named allowance for enumerated sanctioned system writers wearing kind="system"; writes are NOT restructured away from the gates; the enumerated writer list is written as data, not scattered conditionals, so it can one day be a governed object — the first boundary-shaped control (an allowlist) on machine actors.
Findings cited. Investigation findings v0_2: B6/Surprise 10 (masqueraders — FORM_SUBMITTER_ACTOR wears contributor explicitly to pass commit_assertion; _BOOTSTRAP_ACTOR same precedent; root cause: no system kind in ActorKind), Surprise 9 (plural chokepoints — the gates this CR touches are the commit-path family, distinct from the spend gate).
ActorKind gains "system" (src/loomworks/memory/base.py:22). system is a machine kind: it joins NON_HUMAN_ACTOR_KINDS, so the spend tier and every existing machine-actor rejection treat it as non-human by default.SANCTIONED_SYSTEM_WRITERS: frozenset[UUID] beside NON_HUMAN_ACTOR_KINDS in memory/base.py, initially {…0002 (bootstrap), …0050 (form submitter)}, plus a single predicate has_human_commit_authority(actor) (human kinds → True; system + allowlisted id → True; all else → False). The four data-layer human-authority gates (engagement/assertions.py:284/:515/:601, engagement/creation.py:905/:959) and the HTTP dependency gate (api/deps.py:1250) consult the predicate instead of the bare frozenset test — one definition, no scattered conditionals.FORM_SUBMITTER_ACTOR (credit/form_submitter.py) and _BOOTSTRAP_ACTOR (engagement/bootstrap.py) become kind="system"; their docstrings stop justifying the costume and start citing the allowlist. No new masqueraders (O3).ck_memory_events_actor_kind_values to admit 'system' (precedent: migration 0057 widened the same CHECK for 'companion'), plus the ORM CheckConstraint alignment in memory/events.py.agent/companion remain rejected; existing bootstrap/form-submission flows green; suite at zero failures.
Sessions, grantability, presence (W1/W2/W4 — their own CRs). No change to DecidedBySchema or boundary-record deciders (system is not a decider today). No new writers on the allowlist beyond the two named. LEGACY_UNRESOLVED_ACTOR_ID untouched (findings' business, not this CR's).
kind="contributor" on non-person-bound sentinel actors returns zero.