Write Detective Case
Author portable case packages without adding case-specific branches to the
engine. Keep canonical truth private, make every conclusion earnable through a
legal evidence route, and prove the package through explicit public commands
in its own tests/*.yml files.
Load the contract
- Find the repository root containing
package.json, schema/, and cases/.
- Read
docs/case-yaml-reference.md, docs/case-i18n.md, and
docs/detective-tests.md completely
before editing YAML.
- Read
examples/cases/README.md, then inspect the complete smallest package
matching the requested mechanic, including its tests/ directory.
- Inspect
schema/case-source.v0.1.schema.json and
schema/case-test.v0.1.schema.json. Inspect
src/capabilities/catalog.ts when using an unfamiliar field, tool,
template, command, or asset provider. Do not invent vocabulary that the
installed capability registry does not own.
- Inspect an existing full case only for advanced patterns. Do not copy its
story, IDs, hidden truth, or unnecessary complexity.
Treat the schema, compiler, capability registry, and runtime tests as
authoritative when prose documentation and code differ.
Build the case in this order
1. Preserve the brief
- Extract the incident, culprit or explanation, motive, timeline, places,
objects, witnesses, deadline, and desired tone.
- Separate facts supplied by the user from creative assumptions.
- Ask only when a missing choice would materially change the mystery. Make
small reversible assumptions otherwise and record them in the handoff.
- Never silently change the requested solution to make authoring easier.
2. Create a portable package
Use this shape:
cases/<lowercase-kebab-slug>/
case.yml
assets/
i18n/
<case.locale>.yml
tests/
<scenario-id>.yml
Create real assets/, i18n/, and tests/ directories. Bind every catalog
to the exact case ID and version. The default catalog must cover every $text
reference; never put $text in gameplay data. Keep at least one scenario in
tests/; never add a tests: key to case.yml. Use stable lowercase IDs.
Keep the case ID namespaced, for example community.author.case-name, and bump
the semantic version whenever compiled behavior or pinned content changes.
Do not register the slug in engine code; the CLIs discover packages from their
parent directory.
3. Model knowledge before gameplay
- Write immutable canonical events and facts under
truth.
- Put each actor's knowledge, beliefs, statements, omissions, and lies under
perspectives; do not rewrite a belief as world truth.
- Remember that absence means
unknown, not false. Express denial with an
explicit negative polarity.
- Keep event time/validity separate from when a claim or observation is made.
- Check that chronology is physically possible before building clues.
4. Design progressive evidence and affordances
- Start with no investigative evidence when an authored first action can obtain
it. Otherwise grant only the single opening artifact needed to choose that
action. Never bulk-grant footage, logs, notices, interviews, or other clues
the detective should earn.
- Define every player-visible move under
affordances with a localized label,
surface, lifecycle state, and exact action or deduction intent. Add a
case-time cost when the move should consume time. Use localized result
copy for the successful effect, classify risk as normal,
consequential, or terminal, and add localized confirmation copy when a
shell should ask before dispatch. Result copy is revealed only after the move
succeeds. These presentation fields never apply the consequence by
themselves; model it with cost and reactions.
- Include every route-critical
topic, query, tone, evidence, ref, or
routed actor field in the affordance command. Never derive or expect the UI
to derive a move from private unlocks, reactions, truth, or tests.
- Keep action affordances
exclusive: true by default so omitted or altered
arguments cannot bypass their offer state or cost. Set exclusive: false
only for intentional free-form attempts, model their cost or consequence
through a broad reaction, and keep the exact hidden or consumed command
denied.
- Unlock later evidence through typed legal routes such as observation,
interview, search, trust, action, or supported deduction. Offer and withdraw
the corresponding public affordances through authored effects.
- Give every report field a stable observation ID of
<evidence-id>.<report-field>.
- Give player-facing evidence an explicit
presentation. Its localized
title and optional description are visible when granted. Its localized
findings appear only after observation. Every finding key must match a
field in that evidence card's reports; write readable findings for every
report fact the player needs to understand.
- Keep evidence availability separate from observation. Require an explicit
detective observation before a report can support a deduction.
- Make misleading evidence explainably unreliable; do not make it arbitrarily
wrong.
- Demonstrate each required clue's legal route with explicit detective
commands without relying on private truth or automatic planning.
- Provide at least one recovery route after any intentionally premature or
costly action unless the brief explicitly requires a hard failure.
- Keep callable non-caller contacts hidden until localized story copy actually
names them. Author an Inbox
locate-contact affordance anchored to that
opening/evidence/completed-action note, then list the actor and offer their
Phone action unconditionally in the exact matching one-shot reaction. One
lookup must list only its own target. Never infer a name from prose.
- Add a scenario that asserts
contacts: {actor: hidden}, the offered lookup,
and its visible context note, then the accepted zero-cost lookup,
contacts: {actor: listed}, and the callable affordance. For evidence
anchors, assert the evidence is available or observed. For completed-action
anchors, explicitly complete the referenced affordance first. The compiler
proves route structure; the scenario proves the mention path cannot strand
the player.
Use case-specific IDs and copy, but keep this separation:
evidence:
access_log:
tool: log
presentation:
title: {$text: evidence.access_log.title}
findings:
entry_time: {$text: evidence.access_log.findings.entry_time}
unlock: {request: access-log}
reports: {entry_time: "21:04"}
affordances:
request_access_log:
label: {$text: affordances.request_access_log.label}
result: {$text: affordances.request_access_log.result}
risk: normal
confirmation: {$text: affordances.request_access_log.confirmation}
surface: phone
initial: offered
action: {action: request, topic: access-log}
5. Make deductions explicit
- Define the conclusion independently from its proof.
- Express alternative proof routes as DNF: every inner list is an AND route;
the outer
any list is OR.
- Use a legacy term list only when observation presence is genuinely enough.
When a value matters, use an object alternative with
terms and closed
checks such as equals, not_equals, numeric bounds, array membership or
count, and before/after. Include every checked reference in terms.
- Treat observed
false, 0, null, and an empty array as real values;
never confuse them with an unobserved field. Value checks fail closed when a
referenced observation is missing or has the wrong type.
- Require only observations or supported deductions the player can legally
obtain.
- Expose each playable theory as a localized deduction affordance only when the
detective has reached the point where testing it is meaningful.
- Avoid deductions that assert more than their evidence establishes.
- Keep the final conclusion separate from intermediate deductions.
6. Add reactions, time, and endings
- Trigger reactions only from supported deductions, authored actions/decisions,
or emitted events; guard them with supported/observed/flag/schedule
conditions. Trust can gate evidence unlocks or change as an effect, but it is
not a reaction trigger or condition in v0.1.
- Keep reaction effects declarative. Do not mutate runtime state directly.
- Use generic
offer and withdraw effects to advance the public choice set.
Verify that successful affordance commands pay their authored case-time cost
and that denied or unproven commands pay nothing.
- Choose the clock intentionally: wall time continues in the real world,
active time advances during play, and case time represents the fiction.
- Give player-relevant deadlines a localized
label. It is presentation copy,
while clock, after/at, offline, and do remain the schedule logic.
- Make schedule cancellation and shifts idempotent where late evidence may
arrive.
- Write every objective value as a condition mapping; v0.1 can silently omit a
scalar objective.
- Give outcomes explicit priorities and objective requirements. Add a
localized
body when the ending needs more explanation than its title.
- When the case needs a scored result, add one generic top-level
assessment
rubric. Score only facts the case state can prove. Use localized category,
band, met, and missed copy. Make all criterion points add up exactly to
max_score; include a zero score band. Never make the shell infer score from
outcome IDs, translated titles, or private flags.
- Treat every eligible outcome as terminal. If a
replaceable premature
conclusion should remain recoverable, make sure it does not match an outcome;
later commands are rejected with case-ended after any outcome is eligible.
- Cover success, plausible failure, wrong conclusion, and deadline behavior
when those routes exist.
deadlines:
archive_closes:
label: {$text: deadlines.archive_closes.label}
clock: case-time
after: 20m
offline: pause
do: [{emit: archive-closed}]
assessment:
max_score: 100
bands:
- {min_score: 80, label: {$text: assessment.bands.strong}}
- {min_score: 0, label: {$text: assessment.bands.review}}
categories:
reasoning:
label: {$text: assessment.categories.reasoning}
criteria:
identify_source:
points: 100
when: {supported: source_identified}
met: {$text: assessment.criteria.identify_source.met}
missed: {$text: assessment.criteria.identify_source.missed}
outcomes:
solved:
title: {$text: outcomes.solved.title}
body: {$text: outcomes.solved.body}
priority: 100
require: [identify_source]
7. Add assets safely
- Put local media below the package's
assets/ directory.
- Declare its kind, exact MIME type, visibility, source, and lowercase SHA-256.
- Attach assets to evidence by asset ID, never by filesystem path or URL.
- When the brief requests raster evidence, use the built-in ImageGen workflow.
Generate each distinct asset with a purpose-specific prompt, inspect the
result, and iterate when it contains misleading details, unsafe branding, or
visual defects.
- Store the selected project asset under
assets/ as PNG or WebP before
referencing it. Do not leave a case dependency only in ImageGen's generated
output directory.
- Keep every exact playable fact structural under
evidence.*.reports and use
the generated image only as its visual presentation. Do not make a domain,
time, account ID, measurement, identity, or proof term depend on generated
pixels.
- Never substitute a crude placeholder SVG for requested raster evidence. Use
SVG only when the user explicitly requests vector artwork or the asset is
genuinely better represented as deterministic vector data.
- Use HTTPS or a registered provider only when the host has the corresponding
trusted adapter. Keep locators private and pin the exact delivered bytes.
- Generate images or sounds only when requested or required by the brief. Do
not fabricate evidence media merely to fill the folder.
- Recompute the digest after every byte change.
8. Author executable scenarios
- Put one
case-test/v0.1 scenario in each
tests/<scenario-id>.yml. Match scenario.id to the filename stem and match
the exact case ID/version.
- Keep tests private and external to playable case/package/kernel/public IR and
digest inputs. Their only digest is the separate private test-suite digest.
Never copy them into generated public output.
- Write the route in order with
detective.observe, detective.act,
detective.deduce, detective.conclude, detective.advance, and
detective.resume. Never use inline tests, planner goals, prove, use,
use_route, omit, reachable, or solvable test shorthand.
- Add an explicit
expect.result to every important command. Pair intentional
denials with the exact code, such as evidence-locked or
deduction-unproven.
- Assert only public
state: lifecycle status, elapsed clocks, offered/hidden
affordances, hidden/available/observed evidence, opaque asset handle IDs,
exact observations, unknown observations, supported/unknown deductions,
final conclusion, and outcome.
- Never assert truth, perspectives, flags, trust, metrics, schedules, events,
objectives, capability state, or raw asset locators/source descriptors.
Assert media only by the opaque handle ID projected with granted evidence;
static asset
visibility is not a locator-privacy classification.
- Include the shortest complete solution and every materially different proof
route. Add locked evidence, unproven deduction, exact/wrong action,
deadline, offline/resume, optional evidence, early accusation, and wrong
conclusion scenarios when those mechanics exist.
- Make every unlock happen through its actual preceding command. Never let a
test engine invent an event, auto-observe evidence, or auto-prove a
deduction.
- Assert
state.affordances before and after every route-changing action or
deduction. Prove the complete loop: minimal opening, offered localized move,
accepted exact command and time cost, available evidence, explicit observe,
offered deduction, and authored consequence.
- When using
exclusive: false, test a permitted alternate attempt and prove
that the exact authored command still returns affordance-unavailable while
hidden or after one-shot consumption.
Validate before handing off
Run the package compiler and simulator directly so only the target package is
selected:
npx tsx scripts/compile-cases.ts cases/<slug>
npx tsx src/simulator/cli.ts cases/<slug>
For a package under examples/cases/, pass that path instead. If engine,
compiler, capability, package, persistence, or public-build code changed, also
run:
npm run check
Review the generated public manifest and verify that it contains no canonical
truth, private perspectives, unlock conditions, raw asset locators, test
documents, or locked evidence. Confirm that test-only edits do not change case
or public digests. Treat any leak as a blocker.
Do not report success until every external scenario passes through its exact
public command sequence and event-only replay remains deterministic.
Handoff
Report:
- the package path and case version;
- the truth/evidence/deduction shape in a few sentences without spoiling more
than the user requested;
- asset files or external adapters added;
- compiler and detective-test commands run, including exact scenario counts;
- assumptions, intentionally omitted media, and any remaining design choice.
Do not claim the gameplay UI is complete when only the package or headless
engine was changed.
1---2name: write-detective-case3description: Create, extend, review, repair, or validate opencase case packages written as case.yml plus assets/, i18n/, and tests/. Use when an AI must turn a mystery brief into a playable YAML case, add evidence or media, localize presentation copy, design progressive affordances, deductions, or deadlines, write external detective-perspective scenarios, diagnose compiler/test failures, or migrate case-specific code into the generic package format.4---56# Write Detective Case78Author portable case packages without adding case-specific branches to the9engine. Keep canonical truth private, make every conclusion earnable through a10legal evidence route, and prove the package through explicit public commands11in its own `tests/*.yml` files.1213## Load the contract14151. Find the repository root containing `package.json`, `schema/`, and `cases/`.162. Read `docs/case-yaml-reference.md`, `docs/case-i18n.md`, and17 `docs/detective-tests.md` completely18 before editing YAML.193. Read `examples/cases/README.md`, then inspect the complete smallest package20 matching the requested mechanic, including its `tests/` directory.214. Inspect `schema/case-source.v0.1.schema.json` and22 `schema/case-test.v0.1.schema.json`. Inspect23 `src/capabilities/catalog.ts` when using an unfamiliar field, tool,24 template, command, or asset provider. Do not invent vocabulary that the25 installed capability registry does not own.265. Inspect an existing full case only for advanced patterns. Do not copy its27 story, IDs, hidden truth, or unnecessary complexity.2829Treat the schema, compiler, capability registry, and runtime tests as30authoritative when prose documentation and code differ.3132## Build the case in this order3334### 1. Preserve the brief3536- Extract the incident, culprit or explanation, motive, timeline, places,37 objects, witnesses, deadline, and desired tone.38- Separate facts supplied by the user from creative assumptions.39- Ask only when a missing choice would materially change the mystery. Make40 small reversible assumptions otherwise and record them in the handoff.41- Never silently change the requested solution to make authoring easier.4243### 2. Create a portable package4445Use this shape:4647```text48cases/<lowercase-kebab-slug>/49 case.yml50 assets/51 i18n/52 <case.locale>.yml53 tests/54 <scenario-id>.yml55```5657Create real `assets/`, `i18n/`, and `tests/` directories. Bind every catalog58to the exact case ID and version. The default catalog must cover every `$text`59reference; never put `$text` in gameplay data. Keep at least one scenario in60`tests/`; never add a `tests:` key to `case.yml`. Use stable lowercase IDs.61Keep the case ID namespaced, for example `community.author.case-name`, and bump62the semantic version whenever compiled behavior or pinned content changes.63Do not register the slug in engine code; the CLIs discover packages from their64parent directory.6566### 3. Model knowledge before gameplay6768- Write immutable canonical events and facts under `truth`.69- Put each actor's knowledge, beliefs, statements, omissions, and lies under70 `perspectives`; do not rewrite a belief as world truth.71- Remember that absence means `unknown`, not false. Express denial with an72 explicit negative polarity.73- Keep event time/validity separate from when a claim or observation is made.74- Check that chronology is physically possible before building clues.7576### 4. Design progressive evidence and affordances7778- Start with no investigative evidence when an authored first action can obtain79 it. Otherwise grant only the single opening artifact needed to choose that80 action. Never bulk-grant footage, logs, notices, interviews, or other clues81 the detective should earn.82- Define every player-visible move under `affordances` with a localized label,83 surface, lifecycle state, and exact action or deduction intent. Add a84 case-time `cost` when the move should consume time. Use localized `result`85 copy for the successful effect, classify `risk` as `normal`,86 `consequential`, or `terminal`, and add localized `confirmation` copy when a87 shell should ask before dispatch. Result copy is revealed only after the move88 succeeds. These presentation fields never apply the consequence by89 themselves; model it with cost and reactions.90- Include every route-critical `topic`, `query`, `tone`, `evidence`, `ref`, or91 routed actor field in the affordance command. Never derive or expect the UI92 to derive a move from private unlocks, reactions, truth, or tests.93- Keep action affordances `exclusive: true` by default so omitted or altered94 arguments cannot bypass their offer state or cost. Set `exclusive: false`95 only for intentional free-form attempts, model their cost or consequence96 through a broad reaction, and keep the exact hidden or consumed command97 denied.98- Unlock later evidence through typed legal routes such as observation,99 interview, search, trust, action, or supported deduction. Offer and withdraw100 the corresponding public affordances through authored effects.101- Give every report field a stable observation ID of102 `<evidence-id>.<report-field>`.103- Give player-facing evidence an explicit `presentation`. Its localized104 `title` and optional `description` are visible when granted. Its localized105 `findings` appear only after observation. Every finding key must match a106 field in that evidence card's `reports`; write readable findings for every107 report fact the player needs to understand.108- Keep evidence availability separate from observation. Require an explicit109 detective observation before a report can support a deduction.110- Make misleading evidence explainably unreliable; do not make it arbitrarily111 wrong.112- Demonstrate each required clue's legal route with explicit detective113 commands without relying on private truth or automatic planning.114- Provide at least one recovery route after any intentionally premature or115 costly action unless the brief explicitly requires a hard failure.116- Keep callable non-caller contacts hidden until localized story copy actually117 names them. Author an Inbox `locate-contact` affordance anchored to that118 opening/evidence/completed-action note, then list the actor and offer their119 Phone action unconditionally in the exact matching one-shot reaction. One120 lookup must list only its own target. Never infer a name from prose.121- Add a scenario that asserts `contacts: {actor: hidden}`, the offered lookup,122 and its visible context note, then the accepted zero-cost lookup,123 `contacts: {actor: listed}`, and the callable affordance. For evidence124 anchors, assert the evidence is available or observed. For completed-action125 anchors, explicitly complete the referenced affordance first. The compiler126 proves route structure; the scenario proves the mention path cannot strand127 the player.128129Use case-specific IDs and copy, but keep this separation:130131```yaml132evidence:133 access_log:134 tool: log135 presentation:136 title: {$text: evidence.access_log.title}137 findings:138 entry_time: {$text: evidence.access_log.findings.entry_time}139 unlock: {request: access-log}140 reports: {entry_time: "21:04"}141142affordances:143 request_access_log:144 label: {$text: affordances.request_access_log.label}145 result: {$text: affordances.request_access_log.result}146 risk: normal147 confirmation: {$text: affordances.request_access_log.confirmation}148 surface: phone149 initial: offered150 action: {action: request, topic: access-log}151```152153### 5. Make deductions explicit154155- Define the conclusion independently from its proof.156- Express alternative proof routes as DNF: every inner list is an AND route;157 the outer `any` list is OR.158- Use a legacy term list only when observation presence is genuinely enough.159 When a value matters, use an object alternative with `terms` and closed160 `checks` such as `equals`, `not_equals`, numeric bounds, array membership or161 count, and `before`/`after`. Include every checked reference in `terms`.162- Treat observed `false`, `0`, `null`, and an empty array as real values;163 never confuse them with an unobserved field. Value checks fail closed when a164 referenced observation is missing or has the wrong type.165- Require only observations or supported deductions the player can legally166 obtain.167- Expose each playable theory as a localized deduction affordance only when the168 detective has reached the point where testing it is meaningful.169- Avoid deductions that assert more than their evidence establishes.170- Keep the final conclusion separate from intermediate deductions.171172### 6. Add reactions, time, and endings173174- Trigger reactions only from supported deductions, authored actions/decisions,175 or emitted events; guard them with supported/observed/flag/schedule176 conditions. Trust can gate evidence unlocks or change as an effect, but it is177 not a reaction trigger or condition in v0.1.178- Keep reaction effects declarative. Do not mutate runtime state directly.179- Use generic `offer` and `withdraw` effects to advance the public choice set.180 Verify that successful affordance commands pay their authored case-time cost181 and that denied or unproven commands pay nothing.182- Choose the clock intentionally: wall time continues in the real world,183 active time advances during play, and case time represents the fiction.184- Give player-relevant deadlines a localized `label`. It is presentation copy,185 while `clock`, `after`/`at`, `offline`, and `do` remain the schedule logic.186- Make schedule cancellation and shifts idempotent where late evidence may187 arrive.188- Write every objective value as a condition mapping; v0.1 can silently omit a189 scalar objective.190- Give outcomes explicit priorities and objective requirements. Add a191 localized `body` when the ending needs more explanation than its title.192- When the case needs a scored result, add one generic top-level `assessment`193 rubric. Score only facts the case state can prove. Use localized category,194 band, `met`, and `missed` copy. Make all criterion points add up exactly to195 `max_score`; include a zero score band. Never make the shell infer score from196 outcome IDs, translated titles, or private flags.197- Treat every eligible outcome as terminal. If a `replaceable` premature198 conclusion should remain recoverable, make sure it does not match an outcome;199 later commands are rejected with `case-ended` after any outcome is eligible.200- Cover success, plausible failure, wrong conclusion, and deadline behavior201 when those routes exist.202203```yaml204deadlines:205 archive_closes:206 label: {$text: deadlines.archive_closes.label}207 clock: case-time208 after: 20m209 offline: pause210 do: [{emit: archive-closed}]211212assessment:213 max_score: 100214 bands:215 - {min_score: 80, label: {$text: assessment.bands.strong}}216 - {min_score: 0, label: {$text: assessment.bands.review}}217 categories:218 reasoning:219 label: {$text: assessment.categories.reasoning}220 criteria:221 identify_source:222 points: 100223 when: {supported: source_identified}224 met: {$text: assessment.criteria.identify_source.met}225 missed: {$text: assessment.criteria.identify_source.missed}226227outcomes:228 solved:229 title: {$text: outcomes.solved.title}230 body: {$text: outcomes.solved.body}231 priority: 100232 require: [identify_source]233```234235### 7. Add assets safely236237- Put local media below the package's `assets/` directory.238- Declare its kind, exact MIME type, visibility, source, and lowercase SHA-256.239- Attach assets to evidence by asset ID, never by filesystem path or URL.240- When the brief requests raster evidence, use the built-in ImageGen workflow.241 Generate each distinct asset with a purpose-specific prompt, inspect the242 result, and iterate when it contains misleading details, unsafe branding, or243 visual defects.244- Store the selected project asset under `assets/` as PNG or WebP before245 referencing it. Do not leave a case dependency only in ImageGen's generated246 output directory.247- Keep every exact playable fact structural under `evidence.*.reports` and use248 the generated image only as its visual presentation. Do not make a domain,249 time, account ID, measurement, identity, or proof term depend on generated250 pixels.251- Never substitute a crude placeholder SVG for requested raster evidence. Use252 SVG only when the user explicitly requests vector artwork or the asset is253 genuinely better represented as deterministic vector data.254- Use HTTPS or a registered provider only when the host has the corresponding255 trusted adapter. Keep locators private and pin the exact delivered bytes.256- Generate images or sounds only when requested or required by the brief. Do257 not fabricate evidence media merely to fill the folder.258- Recompute the digest after every byte change.259260### 8. Author executable scenarios261262- Put one `case-test/v0.1` scenario in each263 `tests/<scenario-id>.yml`. Match `scenario.id` to the filename stem and match264 the exact case ID/version.265- Keep tests private and external to playable case/package/kernel/public IR and266 digest inputs. Their only digest is the separate private test-suite digest.267 Never copy them into generated public output.268- Write the route in order with `detective.observe`, `detective.act`,269 `detective.deduce`, `detective.conclude`, `detective.advance`, and270 `detective.resume`. Never use inline tests, planner goals, `prove`, `use`,271 `use_route`, `omit`, `reachable`, or `solvable` test shorthand.272- Add an explicit `expect.result` to every important command. Pair intentional273 denials with the exact code, such as `evidence-locked` or274 `deduction-unproven`.275- Assert only public `state`: lifecycle status, elapsed clocks, offered/hidden276 affordances, hidden/available/observed evidence, opaque asset handle IDs,277 exact observations, unknown observations, supported/unknown deductions,278 final conclusion, and outcome.279- Never assert truth, perspectives, flags, trust, metrics, schedules, events,280 objectives, capability state, or raw asset locators/source descriptors.281 Assert media only by the opaque handle ID projected with granted evidence;282 static asset `visibility` is not a locator-privacy classification.283- Include the shortest complete solution and every materially different proof284 route. Add locked evidence, unproven deduction, exact/wrong action,285 deadline, offline/resume, optional evidence, early accusation, and wrong286 conclusion scenarios when those mechanics exist.287- Make every unlock happen through its actual preceding command. Never let a288 test engine invent an event, auto-observe evidence, or auto-prove a289 deduction.290- Assert `state.affordances` before and after every route-changing action or291 deduction. Prove the complete loop: minimal opening, offered localized move,292 accepted exact command and time cost, available evidence, explicit observe,293 offered deduction, and authored consequence.294- When using `exclusive: false`, test a permitted alternate attempt and prove295 that the exact authored command still returns `affordance-unavailable` while296 hidden or after one-shot consumption.297298## Validate before handing off299300Run the package compiler and simulator directly so only the target package is301selected:302303```bash304npx tsx scripts/compile-cases.ts cases/<slug>305npx tsx src/simulator/cli.ts cases/<slug>306```307308For a package under `examples/cases/`, pass that path instead. If engine,309compiler, capability, package, persistence, or public-build code changed, also310run:311312```bash313npm run check314```315316Review the generated public manifest and verify that it contains no canonical317truth, private perspectives, unlock conditions, raw asset locators, test318documents, or locked evidence. Confirm that test-only edits do not change case319or public digests. Treat any leak as a blocker.320321Do not report success until every external scenario passes through its exact322public command sequence and event-only replay remains deterministic.323324## Handoff325326Report:327328- the package path and case version;329- the truth/evidence/deduction shape in a few sentences without spoiling more330 than the user requested;331- asset files or external adapters added;332- compiler and detective-test commands run, including exact scenario counts;333- assumptions, intentionally omitted media, and any remaining design choice.334335Do not claim the gameplay UI is complete when only the package or headless336engine was changed.