npcs/COMPANION_MECHANICS_CONTRACT.md
The exact interface a companion must satisfy to be legal in the ratified systems, and — separately and
explicitly — where that interface leaves real design room. This is a read of the ratified ground, not a
proposal: every mechanism below is already ruled or already schema-landed. Casting and per-companion loyalty
assignment remain Josh's (characterization canon, WS7 L158); this document tells the roster designer what a
companion row/persona MUST contain and what MUST be true of it, so the roster brief proposes only inside the
lines the systems already draw.
Citations are [SRC: path # anchor]. Four files are being mutated by a concurrent lane (T1_Integrity tier
doc, T0_Character_Index, RATE_MISMATCH_ANALYSIS, and CH_17/28/39/56/57); I read them for content but cite
them by section/name, never line number. Everything else is line-cited and verified to resolve.
---
A companion is a person-class entity (T0_Character_Index row + a flagship/supporting persona) that
(a) fills all 13 persona spine fields plus the person extension; (b) carries the **6 companion-loyalty
columns on Character_Index with a legal enum tuple; (c) sits on THE BOND** relational ladder (one shared
−100..+100 numeric axis, companion-axis display labels Enemy…Family) whose movement is a **runtime state
function, not an accumulator; (d) obeys the opposition-magnitude departure rule** (departs on sustained
belief-opposition, investment is inertia but never immunity, complete opposition always forces departure);
(e) is attackability Tier-3 (bonded) — betrayable at maximal cost, never god-moded, never a progression
wall; (f) lives aboard the mothership and may crew sub-craft; (g) may teach or peer a trade, contribute
a combat verb/mode as an ally, and open/close opportunities — but never gates progression (the
no-dead-end invariant; every departure ships a non-empty rerouted_paths). A companion is on the **human/
companion axis; the 22 familiar slots are a separate axis** (WS_012, creature-class, binding-stone) and
must never be conflated.
---
Source of truth: [SRC: docs/proposals/ENTITY_PERSONA_SYSTEM.md # §2.2 L30-44]. The persona extends the
anchor row; it owns no fact the anchor row does not carry (do-not-invent tether). For a companion, each field
has a companion-specific obligation:
CHAR_0NNN row in T0_Character_Index. This is the identity and thedo-not-invent tether. A companion with no clean anchor row is illegal.
one-line essence. Names are naming-canon → flag for Josh per docs/NAMING_METHOD.md.
[SRC: docs/proposals/SIGNIFICANCE_LENSES.md]. This is the relevance ticket AND the anti-museum-flavor
hook: a companion is in the cast because they carry an arc-serving lens, not for decoration.
persona/registry row, mirroring Cross_Cultural_Link_Graph. A companion is a hub in the relational web
[SRC: memory regions-are-relational-webs-not-villages].
This is the §17.1 dependency surface: where a culture's substrate in the corpus is thin, the companion's
history CANNOT be faked — flag book-processing enrichment as the blocker (care = weight + authenticity).
[SRC: memory d06-age-mastery-reclaiming-birthright].
belief axis (§2) that drives departure.
[SRC: docs/RUNTIME_GENERATIVE_LAYER.md # §2.1].
T0_Voice_Registry(only 10 rows today — a thin-anchor dependency).
relationship ledger (companions always do), its starting disposition, and which opportunities its bond
gates. This field is where THE BOND attaches.
T0_Hard_Lines. High-care companionscarry the stricter authenticity bar and the authored-only-at-launch runtime default.
declared; no pre-Ch-76 Grand-Sage or House-pattern leak).
[SRC: docs/RUNTIME_GENERATIVE_LAYER.md # §A]; strategic-tick cadence; authored vs generated; authored
fallback line bank.
[SRC: docs/proposals/ENTITY_PERSONA_SYSTEM.md # §2.4.1 L64-69]
age across revisits.
House-of-Velheim awareness tier, governed by the reveal discipline: no companion may perceive/voice the
family-behind-the-institution pre-~Ch-38, no who-frame, no agent-noun in the safe register
[SRC: memory antagonist-pattern-reveal-timing].
(Interface 6).
Bad, + four biography-shaped: Sympathetic, Detached, Curious, Defiant) in their cultural register
[SRC: _source/01_Tier_1_Foundation/T1_Integrity_Paths_Worldstates_Master [ACTIVE v2.1].md # §6].
protagonist in, read her vital force and hold her secret, or turn hostile-recognizer? This is what the
assimilation mechanic costs and buys through a companion's eyes: a companion who WITNESSES the player's
in-culture integrity choices is the site of a bond swing.
per-slot mechanics (Interfaces 2 + 5).
The living-faithful protection binds companions hardest: a faithful community member is never a combat
target and never the antagonist; no sacred proper name sits on a mortal companion (the Kxao rule); no revered
real person is recast as a villain companion (the Liqä rule) `[SRC: docs/proposals/ENTITY_PERSONA_SYSTEM.md #
§2.4.1 L71; memory deities-real-portrayable-17-1-nuance]`.
---
The 6 columns are live on T0_Character_Index (append zone after the frozen 12-col reference), owner
companion-loyalty, gate-green [SRC: docs/proposals/systems/WS7_WIRING_BUILD_PLAN.md # L136-146]. A
companion row MUST carry a legal tuple:
for_life | invested_sticky | come_and_go | drawn_conditional | not_companion. This is the companion's structural type. not_companion is every non-companion entity (the default for the 157 of
162 rows that are not cast).
unmet | recruitable | traveling | wavering | departed | estranged | bonded_locked —the runtime membership state.
truth_witness_mercy, freedom_from_bondage_redemption, caci_honor_community, craft_and_lineage),
compared against the player integrity band WS_001/WS_002. The vocabulary itself is naming-canon —
propose a set aligned to the T1_Integrity bands for Josh to ratify; seeds are provisional
[SRC: WS7_WIRING_BUILD_PLAN.md # L159].
any_sustained_misalignment | circumstance_only`.
invest_Ch03_active_join_Ch13, drawn_when_integrity_light_L1_L2).
A second column family co-locates on Character_Index and must be kept owner-disjoint (the one-owner-per-
column gate FAILs on a double owner):
attackability_tier + is_load_bearing — owner attackability, NOT companion-loyalty (Interface 7).companion_loyalty_tier ∈ n-a | come-and-go | drawn | invested | for-life — a display alias family; the authoritative model is loyalty_model above [SRC: WS7_WIRING_BUILD_PLAN.md # L172-176].
Hard constraint on population: per-companion assignments are characterization canon = Josh's. Only 5
of 162 rows are seeded, and those seeds are ILLUSTRATIVE — the roster brief must NOT mass-populate the ~30
companion rows before Josh ratifies the roster-wide mapping [SRC: WS7_WIRING_BUILD_PLAN.md # L158].
Known live-data caveats the roster brief inherits (do not silently "fix"):
loyalty_model at all, while Tunde (CHAR_0127), who never travels, carries a full drawn_conditional row. This roster/seed
mismatch is the real open gap — surfaced by the rate-mismatch re-test (RATE_MISMATCH_ANALYSIS, §6). It is
Josh's call and is not yet a ruling slot (a bare "who are the ~30?" is forbidden by the decision
protocol) — Claude authors the roster brief from the spine's own evidence first, then Josh rules.
major_opposition vs planned circumstance_only; Tunde any_sustained_misalignment vs planned major_opposition; CHAR_0003 circumstance vs circumstance_only).
All are illustrative rows Josh rules anyway — note the drift, do not treat any as canon.
---
Ruled by Josh 2026-07-16 [SRC: docs/spine/RELATIONSHIP_TIER_BANDS_BRIEF.md # Rulings 2 & 4 L14-19, L52-64].
One shared numeric ladder across every relational axis (bond_state NPC, standing faction, loyalty_score
companion), −100..+100, with per-axis display labels. The companion axis is THE BOND over
loyalty_score:
| Band | Range | THE BOND label (companion) | THE STANDING label (faction) |
|---|---|---|---|
| Nemesis | −100..−90 | Enemy | Hunted |
| Hostile | −89..−70 | Severed | Banished |
| Wary | −69..−40 | Wary | Suspected |
| Cool | −39..−10 | Cooled | Cooled |
| Neutral | −9..+9 | Stranger | Stranger |
| Friendly | +10..+39 | Known | Welcomed |
| Honored | +40..+69 | Warm | Honored |
| Revered | +70..+89 | Trusted | Revered |
| Exalted | +90..+100 | Family | Exalted |
Rung invariant: only Cooled and Stranger are shared labels, at identical rungs. Family (not Kin) —
"kin" is reserved for the Ch-66 origin-lineage recognition [SRC: RELATIONSHIP_TIER_BANDS_BRIEF.md # L82].
Load-bearing correction (do not build against the accumulator): THE BOND bands a STATE, not a running
total. The ratified runtime moves the bond via a ±-clamped relationship_delta at ~0.03 Hz, and disposition
is "generated fresh each encounter from the current state" `[SRC: docs/RUNTIME_GENERATIVE_LAYER.md # L113-116,
L143; docs/proposals/ENTITY_PERSONA_SYSTEM.md # L137]`. A state bands identically at any event count — so there
is no per-beat accumulator for the roster to design, and the earlier "rate" cardinal was retired
(RATE_MISMATCH_ANALYSIS self-correction). The bond delta and its thresholds are owned by the deterministic
runtime state machine; the roster designer supplies belief axis + join trigger + departure threshold, not
a points budget.
The §17.1 grammar solve (why the labels are safe): every STANDING label is a participle of reception — it
names the player's earned position, never what a people *are* (Sámi: Hunted is safe where Sámi: Hostile is
disqualified). THE BOND labels are a companion's disposition toward the player, same principle
[SRC: RELATIONSHIP_TIER_BANDS_BRIEF.md # L65-70].
---
Ruled [SRC: RELATIONSHIP_TIER_BANDS_BRIEF.md # Ruling 3 L36-51]. Departure is not driven by
loyalty_score — it is driven by the opposition between the player's sustained integrity pattern and the
companion's loyalty_belief_axis pole; the score acts only as inertia.
WS_001/WS_002),not from observed deeds (integrity is a real property read directly).
never = no trigger; complete_opposition = 85; major_opposition = 60; any_sustained_misalignment = 35; circumstance_only = plot-driven, not integrity-driven.
loyalty_score / 10), bonus capped +15, effective triggercapped 90. The 90-cap invariant is ratified and may not be tuned away: opposition tops at 100 > any
reachable trigger, so complete opposition ALWAYS forces departure and investment can never buy immunity
("invested is sticky but not immune," stated as a theorem).
cumulative-pattern rule — a single dark choice never strips a companion).
ratified as authored STARTING VALUES; playtest may move them without a re-ruling, but the SHAPE and
the 90-cap are fixed.
Two ratified-but-inert numbers the roster brief must know (surfaced to Josh, invariant survives):
1. The +15 inertia cap can never bind: it requires loyalty_score = 150, but the domain is −100..+100, so
the max reachable bonus is 10.0. The 90-cap invariant still holds; one stated number is dead
(RATE_MISMATCH_ANALYSIS §self-correction, verified).
2. The "only for_life is exempt" clause is refuted by the live spine: CH_65 stages "Ntala departs," and
Ntala is rowed for_life/never; Josh's D-23 ruling offers departure on every surviving band. The exempt
companion canonically departs. The 90-cap invariant is untouched — only the exemption clause needs
alignment at the wiring commit. **Implication for casting: for_life does not mean "present every node to
the Epilogue"; it means the model's departure trigger is never, which a scripted plot departure (D-23)
can still override.**
---
drawn_conditional companion joins when the player's integrity bandaligns with their belief pole at magnitude ≥ 60, sustained the same two-node way
[SRC: RELATIONSHIP_TIER_BANDS_BRIEF.md # L224; memory companion-loyalty-integrity-system].
for_life (anchor, joins at its trigger and stays), `invested_ sticky (joins on investment, high inertia), come_and_go` (rejoins on corridor returns, leaves by
circumstance), drawn_conditional (DRAWN by aligned integrity, repelled by opposed), not_companion.
The engine drives two worldstate rows (WS7 Increment C, T0_Worldstate_Variables)
[SRC: WS7_WIRING_BUILD_PLAN.md # L147-154]:
companion_roster_state — the live traveling-party ledger: per-member `{character_id,loyalty_model, loyalty_state, loyalty_score(−100..+100), joined_chapter, last_integrity_signature}`.
Membership + loyalty are seeded from the Character_Index anchors. It **REFERENCES WS_008
relationship_history** for encounter history rather than restating it.
companion_loyalty_transition_events — queued `{character_id, event(DRAWN|WAVERING|DEPARTED|REBONDED), chapter, integrity_at_event, rerouted_paths[]}`. **Every DEPARTED event MUST carry a non-empty
rerouted_paths[]** — the no-dead-end contract, enforced by harness/check_no_dead_end.py.
Adjacent variables a companion couples to but must not duplicate: WS_008 relationship_history (general
per-NPC ledger), WS_021 faction_standing_per_faction (THE STANDING axis — separate, Interface 8),
WS_012 familiar_bond_state (the familiar axis — separate, Interface 9). WS_027 references, never restates,
WS_008.
---
Ten canonical trades, each with one ancient + one modern home base, each 12-tier quest-gated (up to 120 gates)
[SRC: registries/T0_Trade_Registry [DRAFT v0.1]/T0_Trade_Registry DRAFT v0.1.csv]:
| ID | Trade | Ancient home | Modern home |
|---|---|---|---|
| TRADE_01 | Animal Communication | Ch 12 W. Africa | Ch 59-65 Africa revisit |
| TRADE_02 | Mining | Ch 19 Persia (Ch 14 Nubia seed) | Ch 59-65 Mid-East revisit |
| TRADE_03 | Blacksmithing | Ch 07 S. India | Ch 60 Japan (tatara steel) |
| TRADE_04 | Herbalism | Ch 07 S. India | Ch 50 Amazon |
| TRADE_05 | Alchemy | Ch 19 Persia | Ch 59-65 Europe revisit |
| TRADE_06 | Tailoring | Ch 21 China | Ch 59-65 Asia revisit |
| TRADE_07 | Culinary Arts | Ch 42 Haiti | Ch 42 Haiti |
| TRADE_08 | Engineering | Ch 27 C. Europe | Ch 59-65 Europe revisit |
| TRADE_09 | Inscription | Ch 15 Egypt + Ch 29 Sámi | ancient-only (paradox-completion) |
| TRADE_10 | Fishing & Navigation | Ch 08 Swahili Coast | Ch 56 Arctic/Greenland |
A companion's teaching_role may make them:
class), gating a mastery-tier climb. Real-science disciplines bind the substrate: Alchemy=chemistry,
Engineering=physics/statics, Herbalism=biology; the game rewards learning the real science
[SRC: memory rewards-intelligence-real-science-immersive-sim].
Non-gating constraint: a trade opportunity a companion opens or closes is by construction
non-progression-critical — the trade climb is completionist/kit, and losing a teacher must reroute to an
equivalent-class alternative (opportunity conservation), never dead-end the trade
[SRC: docs/proposals/ENTITY_PERSONA_SYSTEM.md # §3.4 Mechanism 1-3]. Real trade home-base = an
A_TRADE-layer dwelling with added_modules_only integrity visibility and a cultural_fabric_protected
siting rule (the care firewall — no integrity-scar aesthetics on a living culture's trade home)
[SRC: WS7_WIRING_BUILD_PLAN.md # L216, L246].
---
The fight system is Pillar-8 blended-mode over seven canonical modes: `direct / stealth / puzzle_routed /
environmental / vril_management / familiar / astral [SRC: docs/COMBAT_ENCOUNTER_SYSTEM.md # Part B §2 L143;
_source/.../T1_Combat_System_Spec [ACTIVE v1.0].md § modes]`. Difficulty is world vril-density, never enemy
stat inflation [SRC: COMBAT_ENCOUNTER_SYSTEM.md # Part B §0 L111]. A companion is an ally combatant, and
the contract on what an ally supplies:
— the mode-agnostic posture bar with named sub-nodes, each depletable by a specific mode's verb
[SRC: COMBAT_ENCOUNTER_SYSTEM.md # Part B §5 L196]. A companion whose combat identity is stealth or
puzzle_routed can break a node raw DPS cannot. The ally's mode should compose with, not duplicate, the
player's — the design intent is blended coverage.
real physics), and player, enemies, AND allies all wield both** for good and ill
[SRC: memory vril-altered-physics-real-physics-and-magic]. An ally's contribution is expressed in the same
verb grammar and the same vril-altered-physics substrate, not a separate "buddy AI" system.
NOT tier-6 Vril Sight; a companion cannot read vril-signatures at Neophyte tier
[SRC: memory early-chapter-perception-not-tier6-vril-sight].
familiar Composure node is brokenvia a bonded paired-operation (canon at Ch 73 Sub-Phase C, TGP-exclusive)
[SRC: COMBAT_ENCOUNTER_SYSTEM.md # Part B §5 L196, §3 L160]. This runs on the familiar axis, not the
human-companion axis (Interface 9) — a human companion contributes a human-mode verb; a familiar contributes
the familiar-mode paired-op.
reaches a protected space it is antagonist intrusion, and the environmental-boss protocol (Perception →
Vril-management → Restraint → Purgation) is the playable layer `[SRC: COMBAT_ENCOUNTER_SYSTEM.md # Part A §9
L64; memory rated-r-aaa-dont-defang-monsters]`.
Combat detail (movesets, verbs, counters, phase escalation) is authored per-node at the cascade, not
pre-specified here [SRC: docs/proposals/RELATIONSHIP_COMBAT_SYSTEMS_NOTE.md # §5].
---
The travel model is one transforming vril-flagship mothership + collectible local sub-craft; companions
travel aboard `[SRC: registries/T0_Vehicle_Registry [DRAFT v0.1]/Sheet1.csv; WS7_WIRING_BUILD_PLAN.md #
L12-49]`.
flagship-mothership, acquired Ch 08 (Swahili coast onset), upgradechain raft→dugout→dhow→caravel→research-vessel→submersible-capable, transform configs
cruise;battle;dive;anchored-base. Its crew_station_object names the stations a companion can hold:
helm; lookout; gunner; engineer; cook; menagerie; rigger. **A companion's own_life aboard the mothership
should bind to a crew station** — this is where the "lives aboard" obligation becomes concrete.
z-axis-deep, pilot = bonded-water-familiar/Trade-10), VH_003 the Vimana (peer-flagship, air, Ch 55+; docks as a peer, never carried).
A companion may crew or pilot a sub-craft (e.g. a Trade-10 navigator companion at the helm; a bonded
water-familiar handler piloting the pod).
geography stays walked (no flight pre-Ch-55, F-a); the mothership is a single craft (§6.5), so companions
concentrate aboard one hub, not a fleet of homes. The anchored-base config + the Layer-B dwelling-home
are where a companion resides between deployments [SRC: WS7_WIRING_BUILD_PLAN.md # L215 DW_0002].
Chapter assignments for craft are Josh-canon: only Ch 08 (dhow onset) and Ch 55 (Vimana) are cited; a
companion's boarding chapter must reference an existing acquisition, never mint one.
---
Five attackability tiers, enum hostile | bystander | bonded | protected-collective | shielded
`[SRC: docs/proposals/systems/attackability-and-consequence-model.md # L15, L65; WS7_WIRING_BUILD_PLAN.md #
L166-171]. A companion is Tier-3 (bonded`):
or become an enemy; questlines close; a permanent mark lands. Not god-moded, not invisible-walled —
protected by CONSEQUENCE and BOND, not a can't-target flag `[SRC: attackability-and-consequence-model.md #
L15, L33]`.
is_load_bearing (bool) — true only on the narrow roster of diegetically-resilient main-story figures (spine canon = Josh's). Ntala is the seeded bonded/is_load_bearing=true example
[SRC: WS7_WIRING_BUILD_PLAN.md # L169].
The non-gating invariant governs every companion opportunity `[SRC: docs/proposals/ENTITY_PERSONA_SYSTEM.md
progression_critical and CANNOT be an opportunity; companion-gated affordances are by definition the
complement (kit/route/relationship/lore only).
on all three, each opening/closing different companion opportunities.
alternative on the divergent path (a lost broker reroutes the network).
every DEPARTED ships rerouted_paths[]. Losing a companion reshapes routes; it never blocks the game.
---
Three axes touch a companion; keep them structurally separate:
loyalty_score, WS_027, labels Enemy…Family, driven by integrity-opposition.This is the companion axis.
WS_021 faction_standing_per_faction, labels Hunted…Exalted, aper-faction −100..+100 accumulator, distinct from integrity and from THE BOND
[SRC: _source/.../T1_Integrity_Paths_Worldstates_Master [ACTIVE v2.1].md # §8.7]. A companion has a BOND;
their faction has a STANDING; high BOND does not imply high STANDING with their group.
58), creature-class, bound by binding-stone, tracked by WS_012 familiar_bond_state**
[SRC: COMBAT_ENCOUNTER_SYSTEM.md # Part A §8 L61; memory layer-model-v2]. Familiars are T0_Creature_Roster
/ T0_Familiar_Registry entities (the Familiar_Registry is currently an empty stub, 0 rows — a hard
anchor dependency). A familiar is NOT a companion: it does not carry a loyalty_model, does not sit on
THE BOND, and does not depart on integrity-opposition. WS_012 is heavily written (99 writes / 38 nodes);
WS_008.bond_state (the NPC axis) is genuinely unwritten — do not confuse a bond_state grep with the
familiar axis.
---
one shared numeric axis (Ruling 2 + 4). A per-axis threshold override is the *declined* variant and needs
a NEW Josh ruling; only a per-faction override is tuning `[SRC: RELATIONSHIP_TIER_BANDS_BRIEF.md #
Authority Note L20-32; RATE_MISMATCH_ANALYSIS §8 smuggling-vector]`.
90-cap invariant, WAVERING as a computed band, two-node sustain (Ruling 3).
attackability tiers, companion = Tier-3 bonded**.
rerouted_paths mandatory.and no-flight-pre-Ch-55 firewalls.
authenticity, thin substrate is a book-processing dependency, never faked.
for_life) and Ana (come_and_go) are the two spine-proventravellers, rowed; the Ch-1 best-friend choice seeds Ntala's gender/skills/combat-focus; Ch-58 childhood-
familiar reunion; Ch-65 path-lock; endgame Realm Road 66-77.
1. Roster size (~30). Explicitly Josh's OPEN QUESTION; the "~30" is an unratified scope estimate. The
brief's job is the grounded answer from the spine's staged cast, not a guess.
2. Which canonical figures are companions, and which loyalty_model each carries — including the four
travelling characters (CHAR_0140/0144/0145/0146) that currently carry no model, and whether Tunde's
drawn_conditional fits a one-node presence or he needs more beats (RATE_MISMATCH_ANALYSIS §6). Cardinal —
present as a brief, do not populate.
3. The loyalty_belief_axis controlled vocabulary — the enumerated set of value-poles, aligned to the
T1_Integrity bands. Naming-canon → propose for ratification.
4. Each companion's loyalty_join_trigger (chapter + condition) and loyalty_departure_threshold
assignment — grounded in the companion's motivations/belief pole, within the ratified enums.
5. Each companion's culture, persona, trade lane, combat mode/verb, crew station, and web edges — the
creative-within-vision bulk; apply-and-show-the-path where grounded, but every NAME flags for Josh.
6. The calibration TARGET (design intent, not a number) — e.g. "Ntala → Family at ~Ch-65 path-lock; a
merely-good run misses it." Cheap, genuinely-Josh, guides later authoring when a consumer exists. The
per-beat RATE is retired — do NOT resurrect it as a question.
7. age_stage_presence and come-and-go windows — WHEN each companion is available and rejoins/leaves,
grounded in the arc structure (ancient 2-38 region-per-chapter, modern 39-65, endgame 66-77).
8. Where a culture's substrate is thin — flag the specific book-processing enrichment dependency rather
than author unsupported cultural depth.
---
per-beat "rate" and the "bond-moving beat" filter are named as retired, not silently reused.
name are labelled provisional/illustrative; only Josh's four D-REL-BANDS rulings, the WS7 landed schema, and
the cited T1/CVD hard lines are treated as fixed.