Skip to content

10. Diagnose a Validator-Clean Soft Lock

A campaign can use supported fields, valid IDs, and correct references while still becoming impossible to finish. This chapter creates that failure deliberately.

Start from Checkpoint 9 or download the intentionally broken Checkpoint 10.

  • Why a one-time event is not the same as current state
  • How a condition can make a valid event producer miss its only useful moment
  • How a later consumer can turn one missed event into a soft lock
  • Why normal-path testing is insufficient
  • How to trace producers, consumers, and timing across a dependency graph
  • How to repair the campaign without regenerating unrelated content

Checkpoint 10 differs from the working Checkpoint 9 in only three ways.

1. Remove the current-state completion condition

Section titled “1. Remove the current-state completion condition”

The working recover_letter objective contains:

"completeWhen": {
"hasItem": "tutorial_codex:sealed_letter"
}

The broken variant removes that condition.

The objective can no longer look at the player’s current inventory. It now depends entirely on an action explicitly completing it.

The broken variant adds:

{
"id": "tutorial_codex:fragile_letter_event",
"event": "itemAcquired",
"targetId": "tutorial_codex:sealed_letter",
"once": true,
"when": {
"questActive": "tutorial_codex:missing_courier"
},
"actions": [
{
"completeQuestObjective": [
"tutorial_codex:missing_courier",
"recover_letter"
]
}
]
}

Every field is supported:

  • the event name is valid,
  • the item ID exists,
  • the quest ID exists,
  • the objective ID exists,
  • the condition shape is valid,
  • the action shape is valid.

The problem is timing.

The trigger listens for a moment:

the sealed letter enters inventory

but accepts that moment only when:

The Missing Courier is already active

3. Make Oren depend on the completed objective

Section titled “3. Make Oren depend on the completed objective”

The working Oren branch checks current inventory:

{
"hasItem": "tutorial_codex:sealed_letter"
}

The broken variant replaces that condition with:

{
"objectiveCompleted": [
"tutorial_codex:missing_courier",
"recover_letter"
]
}

This turns the missed acquisition event into a progression gate. Oren will not resolve the letter until the objective says it is complete.

Open the Author tools and validate Checkpoint 10.

The expected result is:

0 errors
0 warnings

That result is not a contradiction. The validator has established that the campaign uses known structures and resolvable references.

It has not established that every required producer can still run before its consumer is needed.

First test the path most authors are likely to try:

talk to Mara
→ start The Missing Courier
→ open the satchel
→ acquire the letter
→ talk to Oren

This path works.

Why?

  1. The quest is active before the item is acquired.
  2. itemAcquired fires for the sealed letter.
  3. The trigger’s questActive condition passes.
  4. The trigger completes recover_letter.
  5. Oren sees objectiveCompleted.
  6. Quest 1 can continue.

A successful normal-path test can therefore create false confidence.

Now use a fresh game and reverse the first two actions:

open the satchel
→ acquire the letter
→ talk to Mara
→ start The Missing Courier
→ talk to Oren

This path fails.

At the moment the letter is acquired:

itemAcquired: tutorial_codex:sealed_letter
questActive: tutorial_codex:missing_courier = false

The trigger’s condition rejects the event.

Later, Mara starts the quest:

questActive: tutorial_codex:missing_courier = true
hasItem: tutorial_codex:sealed_letter = true
recover_letter objective = incomplete

The inventory state is correct, but the campaign no longer observes it.

The itemAcquired event does not fire again merely because the quest became active. The only letter is already in inventory.

Oren then checks:

objectiveCompleted: recover_letter

That condition is false, so the final Quest 1 resolution branch is unavailable.

The campaign is now soft-locked:

  • the file is structurally valid,
  • the player still has the required item,
  • all named content exists,
  • no remaining action can complete the required objective.

The broken graph is:

itemAcquired event
└─ accepted only while Quest 1 is active
└─ completes recover_letter
└─ unlocks Oren's resolution

The letter-first player order is:

itemAcquired event
→ condition fails
→ Quest 1 starts later
→ no second acquisition event
→ recover_letter remains incomplete
→ Oren remains locked

The important defect is not an invalid reference. It is a missing reachable producer after a permitted ordering choice.

Static validation can confirm:

  • itemAcquired is a supported event,
  • the target item exists,
  • the quest and objective exist,
  • questActive is a supported condition,
  • completeQuestObjective is a supported action,
  • Oren’s objectiveCompleted reference is valid.

Static validation generally cannot prove:

  • whether the item can be acquired before the quest starts,
  • whether the item can be acquired more than once,
  • whether an event will be emitted again,
  • whether all player orderings reach the same state,
  • whether another producer can repair a missed event,
  • whether a required dialogue branch remains reachable.

This is why the guide treats validator success as necessary evidence, not sufficient evidence.

Do not begin by rewriting the quest. Trace the smallest failing dependency.

Oren requires:

{
"objectiveCompleted": [
"tutorial_codex:missing_courier",
"recover_letter"
]
}

The blocked consumer is therefore Oren’s Quest 1 resolution branch.

Search for every place that can complete recover_letter.

In the broken checkpoint, the only producer is:

tutorial_codex:fragile_letter_event

There is no completeWhen condition and no second dialogue action that repairs the objective.

The trigger requires all of these to align at one moment:

event = itemAcquired
targetId = tutorial_codex:sealed_letter
questActive = tutorial_codex:missing_courier

4. Ask whether the prerequisite order is guaranteed

Section titled “4. Ask whether the prerequisite order is guaranteed”

It is not guaranteed. The satchel is intentionally available before Mara starts the quest.

The acquisition event for this unique quest item is not a dependable repeatable producer. Possessing the item later does not recreate the original event.

A useful adversarial rule is:

When two actions appear independent, test them in both orders.

For this campaign:

Mara then letter
letter then Mara

Both are supported story paths. Both must work.

Restore the three working decisions from Checkpoint 9.

Restore current-state objective completion

Section titled “Restore current-state objective completion”

Add back:

"completeWhen": {
"hasItem": "tutorial_codex:sealed_letter"
}

Now the objective can reevaluate what is true now, even when the acquisition happened earlier.

Delete:

tutorial_codex:fragile_letter_event

The trigger is unnecessary once the objective observes inventory state directly.

Change Oren’s condition back to:

{
"hasItem": "tutorial_codex:sealed_letter"
}

Oren’s role is to react to the letter the player currently carries. That is the most direct state test for the scene.

You could add dialogue that notices the player has the letter and manually completes the missing objective. That can work, but it would be repairing a fragile model with another special case.

The cleaner design is:

inventory is the authoritative state
→ objective observes inventory
→ Oren observes inventory

One durable fact serves both consumers.

After restoring the Checkpoint 9 logic:

  1. Validate again.
  2. Start a fresh game.
  3. Test Mara first, then the letter.
  4. Start another fresh game.
  5. Test the letter first, then Mara.
  6. Save after acquiring the letter but before speaking to Mara.
  7. Reload, speak to Mara, and confirm the objective completes.
  8. Talk to Oren and confirm Quest 1 resolves.
  9. Repeat the conversation and confirm no duplicate quest transition occurs.

The save-and-reload case matters because it proves the repair depends on durable inventory state rather than a transient event still being in memory.

For every major progression dependency, ask:

Question Example in this campaign
Can the player do this early? Open the courier satchel before speaking to Mara
Can the player do this late? Recruit Lysa after visiting the Belfry
Can the player do this twice? Re-enter the Belfry or repeat dialogue
Can the player do this elsewhere? Enter a different dungeon or defeat another enemy
Can the player save between producer and consumer? Save after the Warden, then return to Oren
Is the event repeatable? Dungeon entry is; unique item acquisition may not be
Is there a durable state fallback? hasItem protects the letter-first path

A campaign reviewer should deliberately search for paths the author did not naturally choose.

Checkpoint 10 adds no legitimate feature. It preserves a known validator-clean failure made from three exact changes:

remove recover_letter.completeWhen
add quest-gated itemAcquired trigger
make Oren depend on objectiveCompleted

The normal path works. The letter-first path soft-locks.

Once you can explain the failure without guessing, return to the working Checkpoint 9 logic. Chapter 11 will package the campaign, validator evidence, dependency ledger, and human playtest results into a release decision.

Continue to Chapter 11: Review, Playtest, and Release.