Skip to content

[EPIC][combat] Recover agentic-first combat while preserving the proven legacy player experience #191

Description

@MoonlightByte

Versioned record: docs/architecture/combat-system-recovery-master.md

Documentation commit: de70ed69

Existing combat and adjacent issues remain independently open and retain their original runtime evidence.


Combat System Recovery Master Record

Status: Canonical scope and architecture record for review. No implementation is authorized by this document.

Recorded: 2026-08-22

Authoritative repository: MoonlightByte/NeverEndingQuest

Pinned current main: 691b5a2f06b472e31c7a123964844d9506862535

Clean historical main baseline: 682103196420687f9cfd3e86dfd2edebe24e5964 (2025-08-22)

Last live-proven pre-agentic main checkpoint: 1c9fdc5cc6ea6460f7fb3d918c93a15a77c636d1

1. Purpose and governing decision

This document records the complete mainline-only assessment of NeverEndingQuest combat after native-Windows browser acceptance exposed combat-integrity, recovery, narration, identity, and provider-liveness defects. It exists to prevent another narrow patch cycle from obscuring the architectural cause or discarding valuable work.

The governing conclusion is:

Preserve the elegant original player experience and preserve the new deterministic, transactional, and recovery machinery. Repair the upstream semantic boundary between them. The model must establish structured scene facts and tactical intent; code must reconcile those facts against canonical state and own mechanics, ordering, arithmetic, persistence, and recovery. Do not infer scenario allegiance from type, prose, names, keyword lists, or regexes.

The current agentic pipeline must not be made mandatory unchanged. It remains contained until the participant/relationship contract is repaired and the full real-headless acceptance matrix passes. This is not a decision to abandon agentic combat or roll back the deterministic substrate.

2. Evidence rules

Every claim in this record uses one of these classes:

  • RUNTIME-OBSERVED: Reproduced through the real native-Windows browser/headless game flow and judged through authoritative runtime state or on-disk files.
  • CODE-PROVEN: Demonstrated by complete current or historical mainline functions, callers, schemas, prompts, diffs, and data flow.
  • HISTORY-PROVEN: Demonstrated by Git ancestry and mainline commits.
  • HYPOTHESIS: A plausible mechanism or proposed architecture that still requires real acceptance.

Cheap or synthetic evidence must not be presented as real gameplay acceptance. No monkeypatch or model-free unit probe proves a live combat seam. Narration is not authoritative evidence of state correctness.

3. Lineage boundary and contamination correction

Only ancestors of pinned origin/main may define shipped behavior or a compatibility baseline.

Included mainline authority

  • 68210319: clean main snapshot from 2025-08-22.
  • 1c9fdc5c: live-proven fresh-game pre-agentic checkpoint. Its commit record documents a two-round Twig Blight combat, XP award, and clean return to the main loop.
  • 27a25ce2: mainline agentic combat rewrite.
  • 06c93ed6: event identity and effect-duration hardening.
  • eb2ecd52: contextual SRD, narration dossier, delivery/recovery, and effect-clock expansion.
  • 6ac9ea44: character leases and stale-state protection.
  • 0314322a: explicit bounded legacy referee verdict.
  • aa2f84d2: code-owned legacy round advancement.
  • Current main through 691b5a2f.

Explicitly excluded as non-authoritative

The following are not ancestors of current main and are not design authority:

  • 832aac22, the unmerged always-agentic rollout switch removal.
  • be3f1943, the separate guidelines branch.
  • 6103fab3, 73a8e457, and the pr117 lineage.
  • Unmerged recruitment/NPC-voice branches such as 25b1913f and c5560742.
  • Ignored local C4 documents, abandoned plans, local transcripts, or debug artifacts.

Those artifacts may be archaeology but cannot define required behavior. Earlier analysis that treated the pr117 family as an approved baseline is withdrawn.

Required new safeguard

A historical compatibility baseline must be an ancestor of the pinned origin/main revision or an explicitly owner-approved shipped release. Non-ancestral branches, worktrees, PR experiments, and local design documents are archaeology only and must never define required behavior.

This rule must be added to the repository's single-source agent guidelines before implementation resumes.

4. Recovered legacy behavioral contract

The historical contract below is recovered from 68210319 and the live-proven pre-agentic checkpoint 1c9fdc5c.

4.1 Adventure-to-combat handoff

  • The main DM semantically decides when awareness plus hostility crosses the Combat Commitment Point.
  • It emits one createEncounter action and stops narratively resolving formal combat.
  • The action contract is limited to player, npcs, monsters, and encounterSummary.
  • Historical combat summaries are explicitly exempt from creating duplicate encounters or rewards.
  • process_ai_response routes the action through action_handler.
  • action_handler starts combat_builder.py, receives the encounter ID, writes worldConditions.activeCombatEncounter, reloads the location, and enters the dedicated combat loop.

4.2 Encounter construction and persistence

  • The builder creates <location>-E<n> encounters.
  • It loads or creates player, NPC, and monster profiles.
  • It assigns d20 initiative and writes modules/encounters/encounter_<id>.json.
  • The durable roster contains creature identity, display name, type, initiative, status, conditions, current/max HP, and action fields.
  • Monsters are materialized as type: enemy; canonical NPCs are materialized as type: npc; the player is type: player.
  • The original representation already conflated source category with broad combat role. This is a legacy limitation, not something invented by the agentic rewrite.

4.3 Player-facing combat experience that must be preserved

  • Combat is a dedicated conversational subsystem with a separate history.
  • It opens with a proper scene rather than a sterile mechanics screen.
  • It provides initiative, creature state, armor class, and exact prepared rolls.
  • Players roll their own attacks, damage, checks, and saving throws.
  • NPCs and monsters consume exact state-provided rolls.
  • The system stops exactly at the player's initiative turn.
  • Consecutive non-player turns are resolved together in initiative order as one cinematic exchange.
  • A submitted player action can close the remaining actor window for the round without repeated "keep going" prompts.
  • Player reactions and saving throws produce deliberate pauses.
  • Out-of-turn player intent is acknowledged and deferred rather than discarded.
  • Narration is second-person, tactically grounded, and ends with a meaningful prompt only when the player owns control.
  • NPC companions retain personality, role, dialogue, tactics, abilities, spells, damage, resources, and XP participation.
  • Quick Roll buttons display dice; they do not submit player input. The player must type the roll result.

4.4 Legacy semantic and reconciliation seam

The old system already contained a partial version of the intended architecture:

  • T046 semantically extracted initiative/acted-state facts from recent prose.
  • Code reconciled identities, statuses, ordering, round, and actor-window shape against the real encounter.
  • Invalid extraction fell back to a deterministic state-derived tracker.
  • T045 authored narration and structured actions.
  • T040 independently refereed the candidate against encounter state and conversation.
  • Rejected candidates were excluded from canonical history and could not mutate state.
  • Code enforced identity consolidation, one encounter update, processing order, XP division, history ordering, and cleanup.

This pattern - agent extracts meaning, code reconciles against state - is the strongest legacy architectural seam to preserve and expand.

4.5 Recruitment and companions

  • Recruitment was a semantic DM decision based on personality, relationship, obligations, and current circumstances.
  • An NPC could agree, refuse, or offer conditional help.
  • On agreement, updatePartyNPCs persisted canonical party membership.
  • The combat DM used companion profiles, roles, attacks, features, spells, dialogue, and prerolls.
  • There was no deterministic consent or eligibility engine.

The legacy path did not provide a proper canonical monster-companion model or typed in-combat relationship transition. That remains an owner-design decision, not permission to infer recruitment from type or prose.

4.6 Save, resume, completion, and handoff

  • activeCombatEncounter is the restart authority.
  • Startup detects it and resumes the real encounter.
  • Combat history is reused only when its encounter marker matches.
  • Resume narration is constrained to a same-round, no-mechanics exchange.
  • Normal victory completion calculated XP, updated allied participants, summarized the fight, recorded the location event, archived the transcript, moved the active encounter to lastCompletedEncounter, and returned a historical summary to the main DM.
  • Archive-before-clear kept incomplete exits restartable.
  • The main DM produced a natural post-combat continuation.
  • Save snapshots included party tracker, encounter files, characters, histories, location, and module state.

5. Proven legacy weaknesses

The original feel is a compatibility baseline; the entire old implementation is not.

  • Mechanical arithmetic and resource changes were model-authored through prose.
  • Update agents reinterpreted prose into absolute JSON mutations.
  • Enemy and allied writes were separate and non-atomic.
  • Narration could be shown before persistence finished.
  • Round arithmetic was partially model-owned and accepted jumps greater than one.
  • sync_active_encounter contained an inverted player-data branch, preventing valid player synchronization.
  • check_all_monsters_defeated read combatants while the schema stored creatures, making its normal auto-exit check ineffective.
  • Player HP/XP presentation could temporarily use stale startup data while later prompt context used refreshed files.
  • XP could be applied before transcript archival; an archival failure preserved the active encounter and could make exit reward replay non-idempotent.
  • Builder success was parsed from human stdout rather than a structured subprocess result.
  • The very large legacy prompt contained internally competing turn/pause instructions.
  • Mainline legacy combat was single-PC. Aborted multi-PC branches do not change that contract.
  • The source contract npcs[] versus monsters[] could not explicitly represent hostile canonical NPCs, allied monsters, neutrals, or multiple sides.

6. Current mainline combat architecture

Current run_combat_simulation retains a large shared/legacy setup and two authority paths inside one monolith.

6.1 Shared entry and setup

  1. T067 emits createEncounter with only player, npcs, monsters, and encounterSummary.
  2. action_handler runs the builder and enters combat synchronously.
  3. The builder hardcodes player/NPC/enemy types.
  4. It stamps the configured pipeline mode into the encounter.
  5. Unstamped historical encounters remain legacy.
  6. The template default on authoritative main remains legacy; agentic mode is opt-in.
  7. Shared setup loads legacy prompt/history, character records, encounter state, prerolls, opening/resume model calls, and presentation context.
  8. Only inside the turn loop does current code choose the agentic or legacy vertical slice.

6.2 Legacy slice still on main

  • T046 initiative extraction.
  • T045 combat author and prose action generation.
  • T040 semantic referee.
  • Prose-mediated encounter and character updates.
  • Model-authored exit with later deterministic hardening.

6.3 Agentic slice on main

  • combat_state owns durable combatant IDs, initiative, cursor, acted set, revision, pending turn, pending delivery, replay ledgers, round, completion receipts, and recovery state.
  • The transaction persists a turn claim before the model call.
  • T096 receives authoritative state, exact required actor IDs, player input, capabilities, and SRD references.
  • The model proposes structured tactical intent.
  • Code validates exact actor order and resolves actors sequentially.
  • Earlier events update the preview used by later actors.
  • Code owns dice, HP, saving throws, resources, effects, event identities, and mechanical invariants.
  • Events are staged before mechanical writes.
  • Character writes occur before the encounter receipt/cursor commit. The design is crash-convergent but not a single atomic multi-file transaction.
  • T097 narrates only after mechanics commit.
  • Narration coverage is checked against stable committed event IDs.
  • Exhausted narration retries use a deterministic committed-fact renderer.
  • Stable delivery IDs permit reconnect replay without rerunning mechanics or narration.
  • Agentic completion applies effect-clock exit, idempotent rewards, area summary, transcript archive, active-pointer cleanup, and completion closure.

6.4 Valuable work to retain

  • Canonical combatant IDs and deterministic initiative tie-breaking.
  • Exact actor windows, revisions, pending-turn claims, and replay ledgers.
  • Structured intents and stable typed events.
  • Sequential preview resolution.
  • Code-owned dice, HP, resources, effects, saves, conservation, ordering, and completion receipts.
  • Leases and state fingerprints protecting concurrent character updates.
  • Crash-convergent replay and recovery.
  • Separation of tactical intent from post-commit narration.
  • Event-ID narration coverage and deterministic fallback.
  • Stable reconnect delivery.
  • Idempotent reward, summary, archive, and completion steps.
  • Persisted per-encounter mode for historical compatibility.

7. Root architectural mismatch

The deterministic engine began one seam too late.

The current T067 action cannot express:

  • canonical participant reference;
  • source kind versus gameplay role;
  • physical presence;
  • player or DM control;
  • side membership;
  • pairwise ally/hostile/neutral relationships;
  • temporary versus permanent alliance;
  • objectives or non-annihilation completion;
  • surrender, escape, betrayal, reinforcement, or recruitment transitions.

The builder therefore uses object shape as semantic truth:

  • monsters[] becomes type: enemy.
  • npcs[] becomes type: npc.
  • Agentic state defaults enemy to hostile.
  • Everything else defaults to party.
  • Strict non-player targeting uses faction difference.
  • Victory depends on the mechanically inferred hostile set.
  • XP, persistence destination, UI overlays, unconscious/death handling, and completion also reinterpret type/faction.

The legacy representation was already incomplete. The agentic rewrite converted that latent convention into hard mechanical authority.

7.1 Code-proven hostile named-NPC failure

For an existing named NPC such as Farmer Willem:

  1. T067 can preserve canonical NPC loading only by placing Willem in npcs[].
  2. The builder stamps type: npc.
  3. State defaults Willem to faction: party.
  4. Strict DM-controlled attacks cannot target same-faction actors.
  5. An adjudicated player action can still damage Willem.
  6. After Willem is defeated, the hostile list remains empty.
  7. Victory requires at least one hostile and all hostiles resolved, so victory remains false.
  8. The living player keeps party defeat false.
  9. Player-control recovery also remains false.
  10. The encounter cannot reach a correct completion state.

Putting Willem in monsters[] makes completion possible but loses the canonical NPC identity and routes him through monster loading/generation. This is not an acceptable workaround.

This chain is CODE-PROVEN against current main. The exact named-NPC scenario has not yet been reproduced through real headless acceptance on the pinned SHA.

7.2 Why more conditions are the wrong fix

Do not add scenario patches such as:

  • if type == npc and hostile-looking...;
  • name or filename guesses;
  • verb lists;
  • keyword/substring/regex checks over narration, descriptions, or reasons;
  • different faction == enemy assumptions;
  • special-case Farmer Willem or any named scenario;
  • silent fuzzy creation when a referenced canonical entity is absent.

Those approaches encode an expanding list of scenarios rather than the model-authored structured fact that code actually needs.

8. Additional current-main concerns found during the audit

8.1 Prose-semantics violations

Current agentic combat includes regex or name-shape decisions that answer semantic questions:

  • inferring requested dice from model-authored prompts;
  • inferring saving-throw ownership from prompt prose;
  • matching dice/spell wording to decide whether a player request is legal;
  • matching prior DM/player prose to reject roll families/results;
  • matching effect names or suffixes to impose mechanical durations;
  • narration acceptance checks based on phrases, titles, numbers, or adjectives;
  • NPC identity resolution through word-overlap fuzzy matching.

These mechanisms may have been added to contain observed failures, but they violate the agentic-first boundary and will grow another scenario list.

8.2 Code-authored tactical choices

  • If a later automatic actor's target becomes stale, code may retarget to the sole opponent or convert the action to defend.
  • Exhausted T096 retries can become a code-authored defend batch.

These are mechanically safe but tactically semantic. The agent should choose a valid alternative from refreshed state; code should only validate and reconcile it.

8.3 Duplicate vertical slices and complexity

Current main retains:

  • two actor-window implementations;
  • two mechanics/state-update engines;
  • two round authorities;
  • two narration flows;
  • two completion protocols;
  • two recovery/persistence models;
  • shared legacy T043/T044/history setup for agentic sessions;
  • type/faction semantics duplicated across builder, state, resolver, pipeline, manager, XP, narration, and UI.

The goal is not a blind deletion. The target design must first preserve the full legacy UX contract and prove the new path before the old path is retired.

8.4 Schema and consumer gaps

  • The encounter schema has no authoritative participant manifest, relation graph, objective, or completion contract.
  • Some pending structures remain broadly typed.
  • XP divides against party-tracker members but agentic reward writes can include loaded non-party NPC records, producing a recipient/divisor mismatch.
  • The UI overlays player HP from a sheet while NPC HP remains encounter-derived.
  • No mainline combat operation currently represents reinforcement, roster mutation, relationship transition, or typed recruitment.

8.5 Confirmed unused/redundant seams

The audit found mainline definitions with no callers, including:

  • combat_agent.select_spell_references;
  • combat_orchestrator._deterministic_narration;
  • combat_manager.merge_updates;
  • deprecated combat_manager.update_json_schema;
  • combat_manager.create_consolidation_prompt.

No removal is authorized until complete consumer and legacy-behavior review confirms they are genuinely dead in the implementation branch.

9. Consolidated issue ledger

The umbrella issue associated with this document coordinates the following existing issues. Their individual runtime evidence remains authoritative and they must not be closed merely because they are linked here.

Core combat scope

Shared identity concern

Adjacent but independently owned

Historical/related evidence to revisit during design

Issues including #66, #79, #81, #105, #108, #109, #123, #124, #146, #147, and #150 contain related encounter commitment, recovery, identity, turn validation, spell, narration/action, and actor-selection evidence. They must be reclassified against the new canonical architecture before reuse; old proposed fixes are not automatically valid.

10. C4 - recovered legacy system

Level 1: system context

flowchart LR
    Player[Player] --> Frontend[Browser / Terminal / Headless Client]
    Frontend --> Game[NeverEndingQuest Runtime]
    Game <--> Provider[Configured Model Provider]
    Game <--> Disk[Campaign, Character, Encounter, History Files]
Loading

Level 2: containers

flowchart TD
    Input[Player prose] --> MainDM[Main DM / T067]
    MainDM --> Dispatcher[Action Dispatcher]
    Dispatcher --> Builder[Encounter Builder Subprocess]
    Builder --> LegacyCombat[Legacy Combat Runtime]
    LegacyCombat --> T046[T046 Initiative Extractor]
    LegacyCombat --> T045[T045 Combat DM]
    T045 --> T040[T040 Referee]
    T040 --> Updaters[Encounter and Character Updaters]
    Updaters --> Files[(Authoritative JSON Files)]
    LegacyCombat --> Summary[Summary / Archive / XP / Handoff]
    Summary --> MainDM
Loading

Level 3: legacy components

  • Session/history matcher.
  • Authoritative context assembler.
  • Character/NPC/monster profile formatter.
  • Preroll cache.
  • Semantic initiative extractor.
  • Structural initiative verifier and deterministic fallback.
  • Deterministic actor-window builder.
  • Combat prompt composer.
  • Candidate generator.
  • JSON/action-shape checks.
  • Semantic referee and fail-closed history finalizer.
  • Enemy encounter updater.
  • Allied character-update consolidator.
  • XP calculator.
  • Combat summarizer and transcript archiver.
  • Active/last-completed lifecycle manager.

11. C4 - current mainline system

Level 2: current containers

flowchart TD
    MainDM[T067 Adventure DM] --> Dispatch[Action Handler]
    Dispatch --> Builder[Combat Builder]
    Builder --> Manager[Combat Manager Shared Setup]
    Manager --> Legacy[Legacy Vertical Slice]
    Manager --> Agentic[Agentic Vertical Slice]

    Legacy --> LModels[T046 + T045 + T040]
    LModels --> LUpdates[Prose-mediated updates]

    Agentic --> T096[T096 Intent]
    T096 --> Kernel[Pipeline / Resolver / Rolls / Events]
    Kernel --> Tx[Transaction / Recovery]
    Tx --> T097[T097 Narration]

    LUpdates --> State[(Filesystem State)]
    Tx --> State
    State --> UI[Terminal / Web / Headless]
Loading

Level 3: current agentic components

combat_builder
  -> type-derived roster and persisted mode
combat_state
  -> IDs, initiative, cursor, revision, pending state, completion state
combat_manager
  -> shared setup, mode branch, actor window, completion, delivery
combat_transaction
  -> claim, stage, apply, recovery, delivery receipt
combat_agent T096
  -> semantic tactical intent for required actors
combat pipeline/resolver/rolls/events
  -> deterministic mechanics and typed facts
combat_agent T097 + combat_narration
  -> committed-fact narration and fallback
filesystem/UI
  -> durable state, reconnect, presentation

12. C4 - required target architecture

Level 1: system context

flowchart LR
    Player[Player] --> UI[Browser / Terminal / Headless]
    UI --> Game[NeverEndingQuest]
    Game <--> Model[Configured AI Provider]
    Game <--> State[Authoritative Campaign State]
Loading

Level 2: containers

flowchart TD
    Input[Player Input] --> DM[T067 Adventure DM]
    DM --> Manifest[Agentic Encounter Manifest]
    Manifest --> Reconcile[Canonical Identity and Relationship Reconciler]
    Reconcile --> Coordinator[Combat Coordinator]
    Coordinator --> Intent[T096 Tactical Intent Agent]
    Intent --> Kernel[Deterministic Mechanics Kernel]
    Kernel --> Commit[Transaction and Persistence]
    Commit --> Narrator[T097 Post-Commit Narrator]
    Narrator --> Output[Browser / Terminal / Headless Output]

    State[(Characters / Party / World / Encounter)] <--> Manifest
    State <--> Reconcile
    State <--> Kernel
    State <--> Commit
Loading

Level 3: component contracts

Agentic encounter manifest

The model reads the real player command plus current party, location occupants, canonical characters, monster sources, relationships, and world state. It returns structured facts only:

  • canonical source reference and display identity;
  • source kind, independent of allegiance;
  • physical presence;
  • controlling authority;
  • side identifier;
  • explicit pairwise relations where required;
  • temporary encounter alliance versus persistent party membership;
  • objectives and completion conditions;
  • surrender, escape, reinforcement, betrayal, and recruitment proposals.

It must not decide arithmetic, file paths, IDs, mutation order, or whether a nonexistent record should be silently invented.

Identity and relationship reconciler

  • Resolves every proposed participant against canonical current state.
  • Assigns stable combatant IDs.
  • Verifies physical presence, ownership, and existence.
  • Refuses only genuinely absent/unowned facts and returns that refusal as narration, not a system error.
  • Never rereads prose.
  • Never uses fuzzy word overlap as final identity authority.
  • Persists the reconciled manifest atomically with the encounter.

Combat coordinator

  • Owns initiative cursor, round, actor windows, pause/resume, defeat/recovery, and completion orchestration.
  • Preserves original initiative cadence and player-roll interaction.
  • Serializes one authoritative turn transaction while allowing safe reconnect/recovery.

T096 tactical intent agent

  • Receives exact eligible actor IDs and refreshed canonical state.
  • Chooses tactics, dialogue, targets, spells, movement, surrender, and other semantic intent.
  • If an intent becomes stale, the agent receives refreshed state and chooses again; code does not invent a tactical retarget or defend action.

Deterministic mechanics kernel

  • Owns dice, legality, distances where represented, damage, healing, HP, death saves, resources, effects, durations, ordering, and conservation.
  • Consumes structured intent and canonical state only.
  • Produces stable typed events with before/after facts.
  • Makes no decision based on prose wording.

Transaction and persistence

  • Owns leases, revisions, state fingerprints, staged events, absolute replay, receipts, and crash convergence.
  • Makes the commit point explicit.
  • After the commit point, advisory work cannot turn a successful state transition into a reported failure.
  • Recruitment/relationship transitions and party persistence must be exactly-once and consistent with encounter state.

T097 narrator

  • Receives only committed structured facts plus personality/context.
  • Describes the player in second person.
  • Preserves NPC voice and cinematic pacing.
  • Cannot introduce new mechanics or mutations.
  • Deterministic fallback renders committed facts without changing them.

Completion resolver

  • Evaluates structured objectives and relations, not type.
  • Supports victory, defeat, surrender, escape, unresolved combat, multiple sides, neutral actors, and relationship changes.
  • Applies rewards exactly once to canonically eligible recipients.

Level 4: intended code ownership

main.py / web/web_interface.py / core/headless/client.py
    interaction and delivery

core/ai/action_handler.py
    encounter routing; no allegiance inference

prompts/system_prompt*.txt and a typed manifest schema
    T067 scene semantics

core/generators/combat_builder.py
    reconciled materialization, not semantic classification

new or refactored encounter-manifest boundary
    identity, sourceKind, controller, sideId, relations, objectives

core/managers/combat_state.py
    initiative, cursor, revision, pending state, relations

core/ai/combat_agent.py
    T096 intent and T097 narration

core/combat/pipeline.py
core/combat/resolver.py
core/combat/rolls.py
core/combat/events.py
    deterministic mechanics

core/managers/combat_transaction.py
    durable commit, recovery, replay protection

core/managers/combat_manager.py
    reduced to coordination and compatibility routing

Required data separation

At minimum, new encounters must separate:

{
  "sourceKind": "character | monster | summon | hazard",
  "sourceRef": "canonical-reference",
  "controller": "player | dm_agent",
  "sideId": "stable-side-id",
  "relations": {"other-side-id": "ally | hostile | neutral"},
  "persistence": "character_sheet | encounter_only"
}

The final schema is owner-controlled. This example records the necessary separation, not final field names or consent to mutate frozen schemas.

13. What to retain, remove, and re-bound

Retain

  • All recovered legacy player-experience behaviors in Section 4.
  • Stable IDs, deterministic initiative, actor windows, rolls, arithmetic, effects, resources, event facts, revisions, leases, recovery, and exactly-once receipts.
  • T096 semantic tactics and T097 post-commit narration.
  • Existing-save compatibility and per-encounter legacy stamping.
  • Full canonical sheets and fresh on-disk state.

Remove only after replacement is accepted

  • npcs[]/monsters[] or type as side authority for new encounters.
  • Faction defaults that make every NPC party and every monster hostile.
  • "different faction means valid hostile target."
  • Regex/keyword inference of dice, ownership, spell identity, duration, narration correctness, or identity.
  • Code-authored tactical retarget/defend decisions.
  • Duplicated legacy vertical slices, but only after real A/B proves the new path preserves their contract.

Re-bound

  • type becomes a compatibility/source adapter, not semantic allegiance.
  • Recruitment becomes a typed semantic outcome reconciled against canonical identity and committed exactly once.
  • Permanent monster companionship, multi-side persistence, and schema changes require explicit owner decisions.
  • Legacy unstamped encounters remain legacy and are never silently rewritten mid-combat.

14. Implementation sequence and stop gates

No implementation should begin until this record is reviewed and accepted as the current design authority.

  1. Add the lineage-authority safeguard to the single-source agent guidelines.
  2. Owner-review and approve this master architecture and the unresolved schema decisions.
  3. Pin an implementation branch to the then-current exact origin/main SHA.
  4. Record the exact legacy behaviors and mainline consumers before editing.
  5. Add real headless acceptance scenarios first.
  6. Introduce the encounter-manifest seam without changing existing legacy encounters.
  7. Reconcile canonical identities and relationships before persistence.
  8. Migrate targeting, completion, XP, UI, recruitment, and persistence consumers together.
  9. Preserve the deterministic agentic mechanics substrate.
  10. Run the full adversarial native-Windows matrix on a real provider and real files.
  11. Run a real A/B against the live-proven pre-agentic player experience where practical.
  12. Independently review architecture, consumers/compatibility, and fail-forward behavior.
  13. Only after acceptance, make new combat agentic by default and remove the hidden rollout switch in a separate reviewed commit.
  14. Retire the legacy path only after existing-save and player-experience parity is proven.

Stop and return to design review if:

  • a proposed fix adds a scenario-specific condition;
  • a semantic decision is inferred from prose, type, name, or shape;
  • a consumer is not mapped;
  • an old working behavior changes outside explicit scope;
  • acceptance requires monkeypatching;
  • a non-main branch is cited as authority;
  • narration is used as state evidence;
  • a schema or player-visible contract is changed without owner approval.

15. Required real-headless acceptance matrix

Every scenario must use the unmodified core/headless/client.py, a pinned SHA, native Windows, a recorded provider/model, one isolated mutable game root, real player commands, and authoritative post-run file inspection.

Scenario Required proof
Standard party versus monsters, legacy/new A/B Opening, initiative cadence, player-owned rolls, NPC voice, cinematic batching, save/resume, XP, archive, and main-DM handoff remain compatible
Missing Quick Roll input Game requests the exact missing roll; no actor replay, skipped player action, or state mutation
Existing hostile canonical NPC Canonical character identity remains intact; hostile relationship drives targeting/completion rather than NPC type
Friendly monster Monster source remains allied and is never counted hostile merely from source kind
Neutral witness/creature Presence persists without forced targeting or blocking completion
Three-sided party/cult/demon fight Explicit relations permit non-player sides to oppose each other without a binary shortcut
Same species/name on opposing sides Distinct canonical references and IDs; no display-name merge or retarget
Party NPC refuses involvement Party persistence remains intact while encounter presence/control follows the agentic fact
Recruit hostile NPC during combat Typed relation transition occurs once; encounter and party records remain consistent
Recruit monster Temporary versus permanent membership is explicit; source kind remains monster; persistence follows owner-approved contract
Failed/nonexistent recruitment Narrated refusal; zero guessed identity or mutation
Betrayal/surrender/charm expiration Exactly one structured relation transition; no stale target legality or premature completion
Reinforcement Canonical source verified; deterministic entry timing; no duplication after restart
Terminal party defeat Clean "Load or Reset" recovery, encounter preserved, no victory finalizer, XP, or auto-load
AC/effect regression Protection fighter remains at canonical AC; no transient invented Defense bonus on disk or in encounter state
Sole-player narration Player addressed in second person over the full combat and post-combat handoff
Identity round trip Display name, canonical ID, and file reference remain consistent without five-attempt no-op loops
Crash/restart matrix Restart at manifest, encounter, pending intent, staged mechanics, relation/recruit, narration, reward, and archive boundaries yields no duplicate turn, recruit, mutation, or XP
Ambiguous/malformed model fact Bounded correction or narrated refusal; no guessed identity and no mutation
Phrasing adversary Diverse natural phrasings resolve to equivalent structured facts without keyword/regex gates
Legacy save Unstamped legacy encounter loads and behaves unchanged; no automatic faction rewrite
Browser reconnect Stable committed output replays without rerunning mechanics or narration
Provider stall during combat/build Tracked separately under #186; no claim of combat semantic acceptance may hide a stalled provider

16. Current runtime acceptance status

17. Master safeguard audit

The repository guidelines already require agentic-first decisions, real-headless acceptance, inspection before claims, legacy preservation, full consumer mapping, evidence classification, and one-item-at-a-time work. Applied prospectively, those safeguards would have identified:

  • no authoritative combat design document on main;
  • no explicit source-kind/side/relation authority;
  • code answering the semantic question "who is hostile?" from object shape;
  • inadequate acceptance limited to ordinary party-versus-monster fights;
  • missing consumer review across prompt, builder, schema, targeting, completion, UI, XP, recruitment, and old saves;
  • non-main artifacts being mistakenly treated as design authority.

This document is therefore the restart gate: it must be reviewed before combat changes resume. It records scope; it does not authorize code.

18. Final decision statement

Do not roll combat wholesale back to the 2025 implementation. Do not enable the current agentic implementation unchanged. Do not repair scenarios through more backend conditions.

Recover the original combat experience, keep the deterministic and transactional improvements, and add the missing agentic encounter-manifest boundary so scenario identity, allegiance, control, objectives, recruitment, and relationships arrive as structured model-authored facts reconciled against real state. Only after the complete native-Windows headless matrix passes should the agentic path become mandatory and the compatibility path be retired.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions