Gap audit 2026-07-29 - lane npc-simulation (9 findings)
Verbatim from workflow wf_d0ca605f-891. Each finding carries either its own register entry id or
the cross-lane merge that absorbed it. This file is the evidence of record the compact register
entries cite.
npc-simulation#1 [CRITICAL] merged into GAP-143 - The witness → memory → community-reaction engine has no spec home and no owner (the ruled "killing ripples through the community")
Vision rules. CLAUDE.md "Content bar" + memory violence-allowed-r17-no-genocide: "killing ripples through the community and is remembered." docs/proposals/systems/attackability-and-consequence-model.md §The engine L22 ("Witness, memory, reputation — not a wanted meter... they witness, flee, warn others, and the community's disposition persists"), L23 community resilience (defends/mourns/rebuilds/escalates settlement→region→hunted-across-the-world), L25 (the baker's empty stall, the grieving family, the child who now fears the player).
What exists (verified). DOCTRINE ONLY, and it defers its own mechanism twice. attackability-and-consequence-model.md §Wiring targets L66 pushes "witness-memory, settlement disposition, reputation, community-resilience/repopulation, escalation ladder, node-control handoff, quest re-skin per holder" to "the WS7 wiring task"; docs/proposals/systems/WS7_WIRING_BUILD_PLAN.md L193 pushes it back out ("belongs to the reputation/integrity WS7 wiring task, NOT this attackability anchor — deliberately out of scope here"). POSITIVE CONTROL on the only candidate home: docs/proposals/systems/reputation-prestige-nemesis.md is 51 lines and contains ZERO occurrences of witness|settlement|ripple|villager|bystander while "reputation" occurs throughout — it specs the WoW-Exalted faction ladder, prestige/NG+, and boss Nemesis AI, not community reaction. Data keys exist with no writer grammar: WS_019 community_state_per_region is the RATIFIED mark_write home (T0_Worldstate_Variables row 19) and the spine already writes reputation_biography_propagation 77 times across 31 nodes and relationship_history 83 times (grep over docs/spine/*.md; control: integrity_score 418). Its own row WS_026 says "full system spec deferred to post-cascade architecture gaps queue at T1_Personal_Dimension_Spec adjacent" — and rank 24's T1_Personal_Dimension_Spec scope is "marriage/partnership, dimension pocket, creature housing" (PRE_5090_BUILD_PLAN L104), which excludes propagation. FACTORY_CONTRACT FR-017 carries the doctrine as a SEED rider with tooth "NONE(the split is a runtime model; the community-ripple half is persona-gated on rank 11)" (docs/factory_contract.json L312-320).
Delta. No document anywhere defines what a kill/harm event WRITES: witness set, propagation radius, decay or non-decay, settlement mobilization, price/greeting/quest-availability deltas, repopulation cadence, or the escalation rungs. 77 authored spine writes land in a system with no spec. Not in ranks 1-30, not in VOL2's LW-*/N8 rows (N8.1 names "community-ripple event on death" as a one-line first version, PRE_5090_BUILD_PLAN L2933).
Blocking. Rank 10 (§7.5 housing-ledger typing over 264 seeds) cannot type dark-track/succession seed variants without the ripple's write grammar; and the first W-LW3 staged playthrough in which the AI QA loop kills a villager has no defined world response — i.e. Gate 1 (Ch 2-13 P3 exit) would certify "consequence" that was never specced. Cheapest before rank 10.
Proposed home. New docs/proposals/systems/COMMUNITY_CONSEQUENCE_ENGINE.md (witness model, WS_019/WS_026 write grammar in STATE_DELTA_GRAMMAR terms, escalation rungs, repopulation cadence) + a factory_contract.json rider with a real tooth + a DOC_MAP row; spec-doc lane, before rank 10.
npc-simulation#2 [CRITICAL] merged into GAP-143 - NPC_recognition_system is a phantom consumer — five worldstate rows name it, nothing specs, owns, or implements it
Vision rules. ENTITY_PERSONA_SYSTEM.md §3.2: "Because integrity is read as a real property, an entity notices who the protagonist has become even without having observed her deeds — the disposition is generated fresh each encounter." This is the whole NPC-reaction surface of the immersive-sim bar.
What exists (verified). NPC_recognition_system is named as a runtime consumer on 5 rows of T0_Worldstate_Variables (WS_001 integrity_score, WS_006 appearance_score, WS_008 relationship_history, WS_023 vril_polarity_signature, WS_025 identity_hiding_status). POSITIVE CONTROL: repo-wide grep finds it ONLY in that CSV plus (a) docs/pipeline_review/lens_wave_2026-07-28/CRITIC_ac-traversal-stealth-legibility.md L117, which independently calls it "the NPC_recognition_system consumer that no system answers to", (b) one prose mechanic in WHOLE_ARC_CONNECTIVE_WEB_INVENTORY.md L106, (c) a 2026-07-20 decision brief — while the same grep found dialogue_resolver in 4 docs including WS7_WIRING_BUILD_PLAN. Engine side: C:\dev\Humanity\Humanity\Source\Humanity\Public has 12 dirs and Core holds HumanityCharacter/HumanityEnemyCharacter/HumanityBossCharacter/HumanityEnemyController — there is NO NPC, persona, companion, or faction class anywhere (find over the whole game repo for *npc*/*persona*/*companion*/*faction* returns one Saved/Telemetry json). N8.2 "AHumanityNpcCharacter persona runtime" is BUILD-NOW (PRE_5090_BUILD_PLAN L2934) with no spec to build against.
Delta. The reaction layer is declared in DATA (which state it reads) and nowhere in DESIGN (what it does with it): no recognition thresholds, no per-band greeting/price/dialogue-availability table, no concealment-vs-recognition resolution order, no authored fallback. Rank 11 personas and the natural-voice dialogue lane both assume it.
Blocking. W-LW3 (LW-8/LW-10 staging) and the natural-voice NPC dialogue lane hit it first: an NPC on screen in the slice must react to integrity/appearance/concealment, and N8.2 has no contract. Also blocks honest QA scoring of "the world reads you."
Proposed home. Either a §recognition chapter of the new COMMUNITY_CONSEQUENCE_ENGINE doc or a T1_Integrity_Paths §8.7 extension, with the token either specced or retired from the 5 worldstate rows in the same commit (a named consumer that answers to nothing is the phantom-registry defect class already recorded in PHANTOM_REGISTRY_ROUTING_FINDING.md).
npc-simulation#3 [CRITICAL] merged into GAP-139 - The persona daily-rhythm has no column anywhere — rank 11's Persona_Index mint spec omits the field LW-8 is queued to read
Vision rules. ENTITY_PERSONA_SYSTEM.md §2.2 own_life: "the entity's daily rhythm and independent existence... This is the field that makes the world feel populated rather than staged." DESIGN_GAP_REGISTER #2 (L68-79) recommends "one shared schedule component with a 3-4 state enum (home/work/social/sleep)". VOL2 L1008 LW-9 explicitly orders "author the slice's ambient/named personas (own_life daily-rhythm, web_edges)".
What exists (verified). ZERO structured home. POSITIVE-CONTROLLED header scan over all 62 registry dirs: no column in any registry matches schedule|routine|occupation|job|population|crowd, while the SAME scan matched trade/home/density columns in 19 registries (T0_Trade_Registry home_base_*, T0_Dwelling_Registry home_id, T0_Region_Index env_density_band_default). T0_Character_Index's 33 columns carry no schedule/home/work field. The queued build row states its own blocker: VOL2 L1040 LW-8 "Ambient-NPC presence/schedule... no schedule field in Character_Index". And the mint that is supposed to unblock it does not add one: ENTITY_PERSONA_SYSTEM §5.2 L218 enumerates the T0_Persona_Index columns as persona_id, anchor_ref, entity class, persona tier, care band, significance-lens set, persona-doc path, runtime class — own_life is NOT among them; it lives as prose in a persona doc. LW-12 (VOL2 L1042) adds a time_of_day ws key but no schedule table.
Delta. LW-8 (queued, W-LW3) and register #2's shared schedule component have no data source: the state enum, the per-persona home/work site refs, and the presence windows exist in no row and in no mint spec. The prose doc is unreadable by a runtime component.
Blocking. Rank 11 itself (PRE_5090_BUILD_PLAN L88, a P1 EXIT criterion) is the last cheap moment — it authors complete personas on every slice entity, so a column added after the mint is a retrofit across every slice persona row; LW-8 at W-LW3 then stalls or ships mannequins.
Proposed home. Amend ENTITY_PERSONA_SYSTEM §5.2 before rank 11 mints: add schedule_state_set (home|work|social|sleep), home_site_ref, work_site_ref, presence_window, plus a child T0_Persona_Schedule table if a persona needs multiple windows; enroll in fk_spec.json in the same commit.
npc-simulation#4 [MAJOR] GAP-158 - The attackability / node-persistence system columns landed and were never populated — 8/164 and 0/76 — and no rider or rank owns the populate
Vision rules. attackability-and-consequence-model.md §65 wires five tiers onto the persona schema plus "a node-persistence schema (node_class: story-anchor / transferable / protected; a succession_chain listing the ordered successor factions; is_load_bearing on the narrow story-critical figures)" — the mechanism that makes killing consequential without dead-ends (§44-51 node succession, quest re-skin per holder).
What exists (verified). Columns exist, data does not. T0_Character_Index (164 rows): attackability_tier filled on 8 rows (5 bonded / 2 protected-collective / 1 hostile), is_load_bearing on 8, loyalty_model on 6, loyalty_belief_axis on 4 — while role and voice_signature_notes are 164/164 and seed_status 164/164, so the registry is richly authored precisely everywhere EXCEPT the system columns. T0_Region_Index (76 rows): node_class filled 5/76, succession_chain 0/76. The seeds are self-declared illustrative (WS7_WIRING_BUILD_PLAN L180-182 "[ILLUSTRATIVE]"), and population was handed off with no owner: FOUNDATION_COMPLETION_PLAN L19 "values/population = re-cascade + Fable-5". The per-chapter obligation register does not ask for it: docs/factory_contract.json holds 70 riders and grep counts attackability=0, faction=0, crowd=0, schedule=0, villager=0, census=0 (control: persona=9, ripple=1, witness=2). docs/spine/RULING_QUEUE_SWEEP.md A4 (L160) proposed the node_class populate; it has not landed and is in no rank.
Delta. 156 of 164 named NPCs have no declared attackability tier and 71 of 76 regions no node class, so nothing in the data says who may be swung at, who is diegetically resilient, or who inherits a node when its holder falls. Not covered by rank 30 (which populates six 1-3-row system registries, not these ACTIVE 164/76-row tables).
Blocking. Rank 10's seed typing and the W-LW3 region staging hit it first — a dark-track seed variant needs succession_chain, and the QA loop's emergent-violence passes need attackability_tier on every NPC it can reach in Ch 2-13.
Proposed home. A derive-from-spine populate pass (the ruled SELECT+RECOMMEND precedent) over Character_Index.attackability_tier/is_load_bearing and Region_Index.node_class/succession_chain, plus a factory_contract rider with an R2 tooth so no chapter can land with unassigned tiers.
npc-simulation#5 [MAJOR] GAP-159 - No faction keyspace: 175 free-text faction tokens, 2 reputation rows, and no faction table for any FK to point at
Vision rules. ENTITY_PERSONA_SYSTEM §2.4.2 makes faction one of the five authoring classes and "the strategic heart of the generative layer"; WS_021 faction_standing_per_faction is canon state keyed on faction_id; the succession chain is "an ordered list of successor factions" (attackability model §46); N8.4 is the per-faction standing subsystem feeding companion recruitment and quest availability (PRE_5090_BUILD_PLAN L2936).
What exists (verified). T0_Character_Index carries faction_affiliations on 150 of 164 rows holding 175 DISTINCT free-text tokens (manggarai_village_flores_council, bali_brahmin_priesthood_lineage, caldh_inter_american_court_legal_coalition …). T0_Reputation_Ladder_Registry = 2 rows (FR_0001 House of Velheim, FR_0002 Swahili coast trade-guild), keyed faction_rep_id, with the ruled 9-band STANDING labels Hunted|Banished|Suspected|Cooled|Stranger|Welcomed|Honored|Revered|Exalted. NO faction registry exists — POSITIVE CONTROL: ls registries | grep -i faction returns nothing while the same grep matches trade and dwelling; corroborated by ENTITY_PERSONA_SYSTEM L75 "there is no standalone faction registry today" and WS7_WIRING_BUILD_PLAN L190 "No FACTION registry exists yet, so succession_chain has no FK target." WS_021's faction_id therefore resolves to no table.
Delta. The join Character → faction → standing → succession → community reaction has no shared key: 175 authored social groups are unnormalized strings, the standing state has no domain, and succession chains cannot be authored even if someone wanted to. Rank 30 populating Reputation_Ladder rows would add rows to a table that is not the faction identity home.
Blocking. N8.4 and LW-10 (the relational-web play surface, W-LW3) hit it first; also blocks the ripple engine's settlement-disposition writes and any per-faction gate on quest availability.
Proposed home. Mint T0_Faction_Index (faction_id PK, culture/region ref, class, care band, reveal-gating) + normalize the 175 tokens into it + repoint WS_021, Reputation_Ladder.faction_rep_id and Region_Index.succession_chain as declared FKs in fk_spec.json; schema-data lane, alongside or immediately after rank 11.
npc-simulation#6 [MAJOR] merged into GAP-139 - No ambient-population bill of materials: no per-zone occupancy anywhere, and the pooled persona buckets have no table
Vision rules. ENTITY_PERSONA_SYSTEM §2.3 tiers ambient entities to "a persona bucket, not an individual bible" and cites the runtime model "a crowd of forty sharing six persona buckets"; regions-are-relational-webs-not-villages and the CVD "unnamed members" directive demand inhabited markets/villages; DESIGN_GAP_REGISTER #5 (L113-124) names density-as-sense-of-place.
What exists (verified). NOTHING countable. The region-page Zone Catalog is 18 columns (flores_island.md L48: zone_id … footfall_surface, care_tier, asset_routing, environment_grammar_refs, zone_space_class) with no occupancy column — footfall_surface is the false friend (walk-surface foley). T0_Region_Index's 26 columns have no population field. The only population metric in the QA budget is a count of NAMED personas: VOL2 QT-17 (L1424) reads "personas (T0_Character_Index 163)" — and that whole named cast is 164 rows for 79 nodes, ~7-8 per slice chapter (Ch_02 Flores 6, Ch_03 7, Ch_04 7, Ch_05 8 … Ch_13 7). No bucket table exists: the header scan over 62 registries returns zero columns matching population|crowd|ambient occupancy (control: 19 registries matched trade/home/density). The spawner that would place them is wildlife-only (VOL2 FA-3).
Delta. There is no number for how many people a village, market, port, or trade compound holds, no bucket roster to pool them onto, and no per-chapter rider asking for either (factory_contract: crowd=0, villager=0, census=0 of 70 riders). The prose exists — flores_island Section 4 People and Culture plus the Section-12 role entries (mosalaki, 'ata madi, tuka timba mata dasi, tu'a teno) — with no row home.
Blocking. Rank 5 (asset_concept/morphology/asset_category/mesh_tags across the slice) hits it first: crowd mesh/material budgets cannot be sized without counts, and W-LW3 staging would otherwise certify "a lit ambient-village frame" against no target.
Proposed home. An ambient_population_band column on the Zone Catalog + Region_Index rail, a T0_Persona_Bucket table (N buckets per culture, each with voice register, dress, occupation set, care band) keyed from the region page's Section-4 role prose, and a QT-17 scorecard metric that reads it.
npc-simulation#7 [MAJOR] merged into GAP-139 - NPCs cannot be shown working the trades: occupation exists only as free text inside role, with no trade FK, no work site, and no practitioner roster
Vision rules. Pillar 9 / the 10-trade system with ancient and modern home bases and 120 quest gates; ENTITY_PERSONA_SYSTEM §2.4.1 teaching_role ("the trade home base, ability, or worldview the person teaches... and the mastery-tier progression they gate"); the immersive-sim bar's economy participation.
What exists (verified). T0_Trade_Registry = 10 rows / 12 columns: trade_id, trade_name, ancient/modern home chapter+region, pillar_9 concept, twelve_tier_quest_gates, home_base_upgrade_ceiling, compound_membership, shared_build_grammar_ref, ceremony_quest_refs. compound_membership is a FACILITY class token (TRADE_01 = "field_infrastructure"), not a roster — no practitioner, staff, or work-site column exists. T0_Character_Index has no occupation or trade column among its 33; the occupational fact is buried unnormalized in the role slug ("aksumite_coffee_ceremony_mistress", "stele_scribe_apprentice_under_monopoly", "manggarai_cotton_ikat_weaver_trade_6_seed_introduction" — role is 164/164 filled). T0_Gather_Node_Registry (24 rows) is player-facing extraction with tool_or_trade_required; no NPC labor side. POSITIVE CONTROL: the registry header scan DID find trade_* columns in 19 registries, so the absence on Character_Index/Persona_Index is real, not a search artifact.
Delta. No structure answers "who practises trade N here, at which site, on what rhythm" — so a trade compound can be built and staffed by nobody, and the schedule component (gap 3) has no work_site to send anyone to. Rank 23 mints the 120 trade-gate quest rows and the Book-of-Trades data home, which is quests, not labour.
Blocking. Rank 23 and the W-LW3 region staging: a trade home base with an upgrade ceiling and no staff roster reads as a prop; also blocks the register-#8 profession-practice feedback loop.
Proposed home. occupation_ref / trade_ref + work_site_ref columns on the rank-11 T0_Persona_Index (mirrored as a normalized token on Character_Index), plus a practitioner-roster column on T0_Trade_Registry's compound rows; schema-data lane with rank 11.
npc-simulation#8 [MAJOR] GAP-160 - Companion out-of-combat life has no policy class and no assignment column — the ally policy registry is 14/14 combat rows
Vision rules. COMPANION_MECHANICS_CONTRACT §8 (L313-334): "companions travel aboard... VH_001's 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"; ENTITY_PERSONA_SYSTEM §2.2 own_life applies to companions as much as villagers; memory companion-loyalty-integrity-system.
What exists (verified). T0_Ally_Behavior_Policy = 14 rows / 21 columns, and every row is combat: domain is the closed §8.11.8 triad (awareness | pattern_detection | proactivity), condition_expr is all local combat flags (enemy_attack_telegraph_visible, threat_on_lower_durability_ally, ward_borne_and_holding), action_ref is attack_directed | interpose | peel | disengage | read_counter_class | lapse_concealment. The schema cannot host a non-combat behavior without a new domain value — the registry's own notes flag the enum as closed. POSITIVE CONTROL: COMPANION_MECHANICS_CONTRACT (439 lines, 12 interfaces) contains ZERO occurrences of camp|banter|idle|out-of-combat|downtime|rest scene while "companion" occurs 93 times. No per-companion station or residence assignment exists: crew_station_object is a text list on the VH_001 vehicle row, and WS_027 companion_roster_state carries loyalty fields only. Rank 22 is "Ally survival/defeat model + ally combat-line class" — combat-scoped.
Delta. Companions have a ruled bond ladder, departure arithmetic, and combat policies, and no specified existence between fights: no station/residence assignment, no downtime behavior rows, no banter or place-reaction surface, no schema slot able to hold one.
Blocking. The STORY_DEPTH order-5 companion-arc typing (blocked on rank 11) and W-LW3's aboard-the-mothership staging from Ch 08 hit it first; also the register-#9 rest/safe-site loop has no companion content to place.
Proposed home. Add an out-of-combat domain (or a companion_presence policy class) to T0_Ally_Behavior_Policy with a declared legal set, plus crew_station_ref / dwelling_ref per member on WS_027 and a station-assignment column authored with the rank-11 personas.
npc-simulation#9 [MINOR] merged into GAP-143 - The escalation / hunted response the doctrine ends on is unbuilt and unqueued — the Hunted band exists as a label with nothing that hunts
Vision rules. attackability-and-consequence-model.md L23: systematic slaughter "escalates diegetic response (settlement to region to hunted-across-the-world) so genocide is never progression-viable"; Josh's own pre-Claude GDD specs the mechanism — docs/original_predclaude/extracted/GDD_Humanity_Game_Complete.md L24120 "13.7 The Bounty System" (operating independently of the Infamy and Renown scales) and L13698 "2 — Hunted Multi-regional. Bounty hunters begin appearing. Movement requires more planning."
What exists (verified). The band NAME shipped without the mechanism: T0_Reputation_Ladder_Registry's ruled STANDING labels begin "Hunted|Banished|Suspected…" (row FR_0001/FR_0002 tier_thresholds) and nothing spawns a hunter off them. docs/original_predclaude/INGEST_GDD.md L155 classifies the bounty system RECOVERED-NEW ("Not in Reputation_Ladder or Tier_C spec; distinct mechanic worth recovering") and L184 proposes "a T0_Bounty_Registry seed" — POSITIVE CONTROL: no bounty registry exists among the 62 registry dirs while the same listing matches trade and dwelling, and no rank 1-30, R-31/32, or VOL2 LW-*/N8 row names bounty, infamy, or hunted-response. The one hunter channel that exists is antagonist-driven (N8.3 Hunter-Trigger over T0_Antagonist_Network_Registry, 64 rows), not player-crime-driven.
Delta. The consequence ladder has a bottom rung (integrity slide) and a top label (Hunted) with no rungs between: no infamy accumulation, no regional spread rule, no hunter spawn or bounty resolution, so the anti-genocide escalation the care doctrine leans on is unimplementable as written and the recovered GDD mechanic is an unqueued orphan.
Blocking. Post-window, but it is what the Ch-5 integrity-gated lethal fork, the gladiator chapters, and any emergent-violence QA pass escalate INTO; recovering it costs one spec pass now and a retrofit across authored reputation writes later.
Proposed home. A hunted-response section appended to docs/proposals/systems/reputation-prestige-nemesis.md (or a T0_Bounty_Registry seed per INGEST_GDD L184), cross-wired to the community-consequence engine's escalation rungs and to N8.3's existing trigger machinery; queue as a POST-window item beside R-31/R-32 so it is never re-derived.
Generated by harness/site/structure_site.py — the URL path is the repo path. review root